Abstract

This paper builds upon previous literature for modeling value-at-risk quantiles that uses an ARMA-style approach by adding ETFs as explanatory variables that are combined into principal component vectors at the forecast origin. By combining these principal component vectors along with various transformations of lagged autoregressive response variables, similar predictive accuracy is achieved (relative to the univariate model) and a clearer interpretation is gained. In fact, this thesis proposes an algorithm to detect changepoints in the explanatory variables that could be used as a means to measure changepoints in the economy. [DELETE IF THE CHANGEPOINT ARGUMENT DOESN’T MAKE SENSE.]

Background and Introduction

When modeling financial time series, simply considering the mean and the variance is insufficient. In fact, modeling a 1% or a 5% quantile of daily returns is a way to understand what happens on the worst days and to have a clearer picture of what might happen during a downturn. Indeed, finance theory suggests that a primary reason why the S&P500, which is a market-capitalization weighted index composed of the 500-largest publicly traded companies in the United States, has earned 6.8% inflation-adjusted pre-tax return with dividend reinvestment from January 1871 through April 2020 (CITE) is because of the risk of a significant downturn. Kerry Pechter at Forbes describes it as a premium for the fact that “stocks are riskier” and “more prone to price fluctuations in the short run” compared to lower risk investments. While the long-run picture of stock returns is a bit clearer, the short-run is a huge question - an investment manager using financial leverage to magnify returns (positive or negative) that could leave them in dire straits if their investments fell rapidly, despite a sound long-run strategy.

While there are other ways to understand and measure downside risk, a commonly accepted means is using value-at-risk (VaR). The metric is understood as follows: a one-day 1% VaR of -1 million dollars for a portfolio means that the portfolio will lose at least $1 million on the 1% worst trading days. A major advantage of VaR is that it distills a distribution of returns into one number. As such, VaR is often used in stress testing by regulatory agencies in the United States, the United Kingdom, and Europe (CITE).

Many of the approaches for modeling VaR rely on a semiparametric or a nonparametric historical simulation (ADD CITATION - BOUDOUKH). According to Robert Engle and Simone Manganelli in a 2004 paper, these methods are usually chosen for “empirical justifications rather than on sound statistical theory” (ADD CITATION - ENGLE). As such, they propose a framework called CAViaR that forecasts the VaR quantile directly using a conditional autoregressive quantile specification. This approach builds upon the statistical literature that extends linear quantile models to settings amenable to financial modeling, such as with heteroskedastic and nonstationary error distributions (ADD CITATION - KOENKER, PORTNOY).

Methods Used

A common problem in statistical analysis occurs when a training sample is significantly different than that of the test sample. Initial motivations for this paper involved analyzing two stocks - Amazon (ticker: AMZN) and Proctor & Gamble (ticker: PG) and their performance during the great recession. A relevant question of a financial institution would understandably be how their risk model performed during 2008, a highly volatile period which was driven by the “worst financial crisis since the Great Depression” according to Gary Becker (CITE), a Nobel-prize winning Economist. Interestingly, the forecast for Amazon was fairly accurate whereas the forecast for PG was not. One reason for this could be the fact that a stock like Amazon was highly volatile during the training sample, which included data from previous years (HOW MANY?), but PG was fairly calm. How would it be possible for a univariate model such as CAViaR, that does not explictly account for other factors, to forecast well? What if a volatile stock such as AMZN was included into the forecast for PG - would it improve the forecast?

Thus, the idea of combining stocks into a multivariate setting to capture correlations and better forecast risk was formed. A natural choice appeared to be the diffusion index model, originally developed by Stock and Watson for predicting conditional means [TWO CITATIONS]. The model for forecasting the conditional mean is specified below.

Diffusion Index Model

A useful means of predicting stock movements in the future is the Stock and Watson diffusion index. The model is outlined below, which is adapted from Multivariate Time Series Analysis With R and Financial Applications by Ruey S. Tsay [ADD CITATION].

There are two relevant equations:

\[ \boldsymbol{z_t} = \boldsymbol{Lf_t} + \boldsymbol{\epsilon_t} \]

and

\[ y_{t+h} = \boldsymbol{\beta^\prime f_t} + \boldsymbol{e_{t+h}} \]

In the first equation \(\boldsymbol{z_t} = (z_{1t}, ...., z_{kt})^\prime\) is an observed time series with mean 0, \(\boldsymbol{f_t}\) is an m-dimensional vector of common factors with mean 0 and identity covariance matrix, \(\boldsymbol{L}\) is a \(k\) x \(m\) loading matrix, and \(\boldsymbol{\epsilon_t}\) is a i.i.d. sequence of random vectors with mean 0 and covariance matrix \(\boldsymbol{\Sigma_e}\).

In the second equation, which represents the h-step ahead prediction based on \(\boldsymbol{f_t}\), \(y_t\) is the scalar time series of interest, \(h\) is the forecast horizon, \(\boldsymbol{\beta}\) represents the vector of coefficients, and \(e_t\) is a sequence of uncorrelated random variables with mean 0 and constant variance.

To model the data, principal component analysis is performed on the covariates described below to obtain an estimate of \(\boldsymbol{f_t}\). Then the \(\boldsymbol{\beta}\) coefficients are estimated using ordinary least squares.

CAViaR Model

However, work needed to be done to align the diffusion index model with the CAViaR model, which is defined below. The following variables are required for use in the CAViaR model:

A vector of portfolio returns

Adaptive CAViaR Model

\[ f_t(\beta_1) = f_{t-1}(\beta_1) + \beta_1\left[\left(1+ \exp(G[y_{t-1} - f_{t-1}(\beta_1)]) \right)^{-1} - \theta \right] \]

Symmetric Absolute Value CAViaR Model

\[ f_t(\boldsymbol{\beta}) = \beta_1 + \beta_2f_{t-1}(\boldsymbol{\beta}) + \beta_3|y_{t-1}| \]

Asymmetric Slope CAViaR Model

\[ f_t(\boldsymbol{\beta}) = \beta_1 + \beta_2f_{t-1}(\boldsymbol{\beta}) + \beta_3(y_{t-1})^+ + \beta_4(y_{t-1})^- \]

Indirect GARCH (1,1) CAViaR Model

\[ f_t(\boldsymbol{\beta}) = (\beta_1 + \beta_2f_{t-1}^2(\boldsymbol{\beta}) + \beta_3y_{t-1}^2)^{1/2} \]

[ADD SPECIFICATION]

As such, the following model is used to combine the two ideas:

VAR = INTERCEPT + PAST VALUES + AR COMPONENT + ERROR

Data Used

The response variable used in this analysis is SPY, which is an exchange-traded fund that aims to track the performance of the S&P 500, which is discussed above. It is broadly used as a bellweather of the U.S. economy (CITE), and has the advantage of avoiding survivorship bias - while an individual stock might go bankrupt or merge with another, it’s reasonable to assume that these issues do not apply with an ETF.

Following this logic, there are several classes of response variables used in this analysis. The first group is a set of U.S. sector ETFs obtained from Seeking Alpha using the link below. As with the response variable, these ETFs were publicly traded throughout the Great Recesssion.

https://seekingalpha.com/etfs-and-funds/etf-tables/sectors

  1. Utilities (XLU)
  2. Consumer Staples (XLP)
  3. Healthcare (XLV)
  4. Technology (XLK)
  5. Consumer Discretionary (XLY)
  6. Industrial (XLI)
  7. Financial Services (XLF)
  8. Basic Materials (XLB)
  9. Energy (XLE)

The second is Global Sector ETFs, also obtained from Seeking Alpha. The rationale for including these is that perhaps some global exposure is useful in understanding the broader market.

  1. Utilities (JXI)
  2. Consumer Staples (KXI)
  3. Healthcare (IXJ)
  4. Telecommunications (IXP)
  5. Technology (IXN)
  6. Consumer Discretionary (RXI)
  7. Industrial (EXI)
  8. Financial Services (IXG)
  9. Basic Materials (MXI)
  10. Energy (IXC)

The third is bond ETFs, also obtained from [CITE]. Like the previous two, these ETFs potentially contain forward-looking information about the stock market. Link below:

  1. iShares 1-3 Year Treasury Bond Fund (SHY)
  2. iShares 7-10 Year Treasury Bond Fund (IEF)
  3. iShares 20+ Year Treasury Bond Fund (TLT)
  4. iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

Lastly, all of the above are run together.

Results

The working directory was changed to /Users/stevenmoen/Documents/GitHub/CAViaR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.

Big Simulation Function

Problem Solving on 4.29.2020

2008 Ending

U.S. ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.046 1.1 1.371 1.265 0.208 0.213 0.219 0.355
VaR Breaks (%) 0.200 0.2 0.212 0.208 0.028 0.028 0.028 0.060
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.319 1.344 1.768 1.385 0.651 0.654 0.640 0.956
VaR Breaks (%) 0.260 0.236 0.340 0.260 0.076 0.076 0.064 0.160
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.623 1.564 1.738 1.534 1.077 1.066 1.068 1.366
VaR Breaks (%) 0.328 0.312 0.348 0.332 0.144 0.156 0.140 0.224
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Global ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.740 0.761 0.841 0.867 0.208 0.213 0.219 0.355
VaR Breaks (%) 0.108 0.112 0.120 0.108 0.028 0.028 0.028 0.060
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.160 1.173 2.157 1.283 0.651 0.654 0.640 0.956
VaR Breaks (%) 0.176 0.172 0.412 0.184 0.076 0.076 0.064 0.160
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.517 1.517 1.791 1.523 1.077 1.066 1.068 1.366
VaR Breaks (%) 0.284 0.284 0.348 0.288 0.144 0.156 0.140 0.224
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Commodity ETFs

Bond ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.891 1.017 1.271 1.090 0.208 0.213 0.219 0.355
VaR Breaks (%) 0.156 0.168 0.224 0.128 0.028 0.028 0.028 0.060
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.338 1.316 1.659 1.325 0.651 0.654 0.640 0.956
VaR Breaks (%) 0.236 0.236 0.316 0.256 0.076 0.076 0.064 0.160
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.641 1.575 1.840 1.586 1.077 1.066 1.068 1.366
VaR Breaks (%) 0.308 0.304 0.364 0.308 0.144 0.156 0.140 0.224
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

All ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.736 0.737 1.733 0.863 0.208 0.213 0.219 0.355
VaR Breaks (%) 0.104 0.108 0.216 0.104 0.028 0.028 0.028 0.060
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.148 1.236 2.391 1.371 0.651 0.654 0.640 0.956
VaR Breaks (%) 0.168 0.208 0.400 0.220 0.076 0.076 0.064 0.160
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 1.521 1.549 1.797 1.644 1.077 1.066 1.068 1.366
VaR Breaks (%) 0.284 0.288 0.344 0.292 0.144 0.156 0.140 0.224
Note:
Calculated using 250 trading days from 2008-01-04 to 2008-12-30

2010 Ending

U.S. ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.128 0.119 0.155 0.128 0.079 0.08 0.086 0.191
VaR Breaks (%) 0.000 0.000 0.044 0.000 0.020 0.02 0.016 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.369 0.369 0.468 0.379 0.336 0.336 0.343 0.492
VaR Breaks (%) 0.028 0.028 0.084 0.028 0.052 0.052 0.048 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.56 0.561 0.710 0.572 0.547 0.549 0.546 0.690
VaR Breaks (%) 0.08 0.072 0.132 0.080 0.080 0.088 0.084 0.028
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Global ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.133 0.136 0.110 0.127 0.079 0.08 0.086 0.191
VaR Breaks (%) 0.000 0.000 0.004 0.000 0.020 0.02 0.016 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.386 0.371 0.449 0.401 0.336 0.336 0.343 0.492
VaR Breaks (%) 0.024 0.024 0.068 0.024 0.052 0.052 0.048 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.606 0.606 0.664 0.590 0.547 0.549 0.546 0.690
VaR Breaks (%) 0.040 0.040 0.128 0.068 0.080 0.088 0.084 0.028
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Commodity ETFs

Bond ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.131 0.13 0.129 0.128 0.079 0.08 0.086 0.191
VaR Breaks (%) 0.000 0.00 0.016 0.004 0.020 0.02 0.016 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.373 0.372 0.494 0.378 0.336 0.336 0.343 0.492
VaR Breaks (%) 0.028 0.028 0.104 0.028 0.052 0.052 0.048 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.566 0.565 0.659 0.578 0.547 0.549 0.546 0.690
VaR Breaks (%) 0.076 0.076 0.128 0.080 0.080 0.088 0.084 0.028
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

All ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.146 0.136 0.114 0.128 0.079 0.08 0.086 0.191
VaR Breaks (%) 0.000 0.000 0.000 0.000 0.020 0.02 0.016 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.394 0.394 0.436 0.397 0.336 0.336 0.343 0.492
VaR Breaks (%) 0.024 0.024 0.068 0.028 0.052 0.052 0.048 0.000
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.595 0.594 0.664 0.596 0.547 0.549 0.546 0.690
VaR Breaks (%) 0.044 0.044 0.120 0.076 0.080 0.088 0.084 0.028
Note:
Calculated using 250 trading days from 2010-01-05 to 2010-12-30

2014 Ending

U.S. ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.083 0.075 0.173 0.071 0.061 0.057 0.063 0.061
VaR Breaks (%) 0.000 0.000 0.072 0.004 0.008 0.004 0.012 0.028
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.242 0.241 0.229 0.238 0.226 0.218 0.225 0.240
VaR Breaks (%) 0.024 0.028 0.044 0.032 0.052 0.048 0.052 0.056
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.388 0.362 0.368 0.367 0.367 0.359 0.364 0.368
VaR Breaks (%) 0.060 0.056 0.080 0.076 0.116 0.104 0.112 0.132
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Global ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.076 0.074 0.158 0.071 0.061 0.057 0.063 0.061
VaR Breaks (%) 0.000 0.000 0.096 0.000 0.008 0.004 0.012 0.028
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.240 0.245 0.241 0.245 0.226 0.218 0.225 0.240
VaR Breaks (%) 0.024 0.028 0.040 0.024 0.052 0.048 0.052 0.056
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.377 0.358 0.388 0.358 0.367 0.359 0.364 0.368
VaR Breaks (%) 0.056 0.048 0.084 0.068 0.116 0.104 0.112 0.132
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Commodity ETFs

Bond ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.079 0.075 0.072 0.070 0.061 0.057 0.063 0.061
VaR Breaks (%) 0.000 0.000 0.000 0.004 0.008 0.004 0.012 0.028
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.241 0.237 0.231 0.237 0.226 0.218 0.225 0.240
VaR Breaks (%) 0.028 0.012 0.040 0.024 0.052 0.048 0.052 0.056
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.370 0.364 0.371 0.352 0.367 0.359 0.364 0.368
VaR Breaks (%) 0.056 0.044 0.072 0.064 0.116 0.104 0.112 0.132
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

All ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.087 0.073 0.107 0.079 0.061 0.057 0.063 0.061
VaR Breaks (%) 0.008 0.008 0.052 0.008 0.008 0.004 0.012 0.028
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.241 0.256 0.320 0.246 0.226 0.218 0.225 0.240
VaR Breaks (%) 0.024 0.032 0.084 0.028 0.052 0.048 0.052 0.056
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.371 0.359 0.370 0.361 0.367 0.359 0.364 0.368
VaR Breaks (%) 0.056 0.044 0.072 0.056 0.116 0.104 0.112 0.132
Note:
Calculated using 250 trading days from 2014-01-03 to 2014-12-30

2016 Ending

U.S. ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.087 0.093 0.085 0.09 0.078 0.082 0.078 0.077
VaR Breaks (%) 0.020 0.020 0.028 0.02 0.012 0.020 0.012 0.004
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.278 0.297 0.257 0.290 0.238 0.238 0.234 0.264
VaR Breaks (%) 0.064 0.056 0.080 0.068 0.032 0.040 0.028 0.032
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.419 0.415 0.401 0.429 0.370 0.373 0.368 0.414
VaR Breaks (%) 0.104 0.100 0.120 0.108 0.088 0.092 0.096 0.072
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Global ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.09 0.098 0.085 0.087 0.078 0.082 0.078 0.077
VaR Breaks (%) 0.02 0.020 0.028 0.016 0.012 0.020 0.012 0.004
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.279 0.261 0.253 0.291 0.238 0.238 0.234 0.264
VaR Breaks (%) 0.068 0.040 0.048 0.080 0.032 0.040 0.028 0.032
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.419 0.400 0.400 0.442 0.370 0.373 0.368 0.414
VaR Breaks (%) 0.104 0.096 0.116 0.112 0.088 0.092 0.096 0.072
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Commodity ETFs

Bond ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.076 0.089 0.108 0.085 0.078 0.082 0.078 0.077
VaR Breaks (%) 0.012 0.024 0.028 0.016 0.012 0.020 0.012 0.004
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.257 0.265 0.273 0.273 0.238 0.238 0.234 0.264
VaR Breaks (%) 0.040 0.044 0.060 0.060 0.032 0.040 0.028 0.032
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.402 0.395 0.397 0.415 0.370 0.373 0.368 0.414
VaR Breaks (%) 0.100 0.096 0.108 0.084 0.088 0.092 0.096 0.072
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

All ETFs

Comparison of VaR Methods for a 1% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.091 0.097 0.092 0.083 0.078 0.082 0.078 0.077
VaR Breaks (%) 0.020 0.020 0.028 0.016 0.012 0.020 0.012 0.004
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 5% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.26 0.265 0.283 0.272 0.238 0.238 0.234 0.264
VaR Breaks (%) 0.06 0.048 0.092 0.056 0.032 0.040 0.028 0.032
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Comparison of VaR Methods for a 10% VaR
M1 M2 M3 M4 M5 M6 M7 M8
Losses 0.425 0.397 0.401 0.441 0.370 0.373 0.368 0.414
VaR Breaks (%) 0.096 0.096 0.112 0.100 0.088 0.092 0.096 0.072
Note:
Calculated using 250 trading days from 2016-01-06 to 2016-12-30

Conclusions and Future Work

The problem of how to predict a low quantile of a stock’s log return when the training sample is substantially different than the test scenario is an enormously difficult problem. Almost axiomatically, the distribution is nonstationary over time. How is it possible to predict the return of an index like the S&P500 during a period of market turmoil such as the great recession? While the CAViaR model performs comparatively well during times of stress, it performs about the same as the multivariate model during more benign economic periods.

This conclusion drawn from the above results might support the notion of combining the two models in some sort of a mixture model - aiming to use the basket of ETFs during good times, and use the CAViaR ARMA specification during bad times. The approach of using ETFs allows a prediction based on forward-looking expectations of fundamental factors. Indeed, ETFs are just baskets of individual stocks or bonds, and those securities are (in theory) based on rational expectations about future resources, market conditions, etc - the microfoundations of what drives our economy. The ARMA specification, while practically and statistically sound, is contradicted by economic theory and practice - the weak form of the efficient market hypothesis states that it is impossible to forecast future values of asset prices using past values. But perhaps this view is incomplete.

Any model that attempts to capture relationships in the real world will only work until an omitted variable is found. The elegance of the multivariate CAViaR model is that it provides insight into why a prediction is wrong; the change in the angle between resultant vectors is a sensible measurement of economic changepoints (CHANGE). However, errors in the world are costly, and it’s wishful thinking to say that explaining why the error occured is sufficient.

As such, for future work it’s worth exploring the notion of weighting an ARMA-approach more heavily when predictions using fundamentals were too high, then not only would this after-the-fact recognition be achieves, but also a hierarchical model that captures fundamental relationships in the economy and potentially changes our understanding of asset prices in general - a synthesis between Keynes’ animal spirits during a time of severe crisis; where a model cannot explain shifts, and a more rational world that explains other periods. In addition to significant predictive power because of the switching between the two worlds, there’s also an elegant explanation; a way to explain changes in the usefulness of the underpinnings in the economy. Because of the flexibility of the model, it’s entirely possible that a whole gamut of variables could be tossed in and backtested to when “changepoints” occurred.

Additional future work involves developing theoretical guarantees on the parameters in the multivariate CAViaR model. One advantage of both the diffusion index model and the CAViaR model is that both have theorems about asymptotic normality and consistency [CONFIRM].

Code Appendix

knitr::opts_chunk$set(fig.width=12, fig.height=8, fig.path='Figs/',
                      echo=FALSE, warning=FALSE, message=FALSE, cache = TRUE)
# Read in relevant libraries
library(microbenchmark)
library(data.table)
library(quantmod)
library(ggplot2)
library(tseries)
library(zoo)
library(magrittr)
library(dplyr)
library(kableExtra)
library(formattable)
library(quantreg)
library(MTS)
library(plot3D)
library(citr)

# Set up working directory
# setwd("~/Documents/GitHub/CaviaR")

# source('caviar_SM.R')
source('~/Documents/GitHub/CaviaR/caviar_SM.R')
# This code below is for use in the CAViaR sections.
# Here is code that I'll wrap some parts in to avoid superfluous output
quiet <- function(x) { 
  sink(tempfile()) 
  on.exit(sink()) 
  invisible(force(x)) 
} 
#' This is a function which pulls data for use in the CAViaR model
#'
#' @param symbol - symbol to pull
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices. Default is yes.
#' @param log_return - use log return? Default is yes.
#'
#' @return - a data frame which can be fed into later functions
#' @export
#'
#' @examples - data_pull("SPY")
data_pull = function(symbol, compl_case = 1, adj_close = 1, log_return = 1, start_date = "1900-01-01", end_date = Sys.Date()){
  # Pull in data from quantmod
  response_pull = getSymbols(symbol, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (adj_close == TRUE){
    df = Ad(response_pull)
  } else {
    df = Cl(response_pull)
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    df = df[complete.cases(df), ]
  } else{
    df = df
  }
  # Calculate log return of data
  if (log_return == TRUE){
    lr = log(df[,1]/shift(df[,1], 1, type = "lag"))
    # Combine data
    df_out = cbind(df, lr)
    # Rename the data 
    colnames(df_out) <- c(sym=symbol, paste0(symbol, "_log_return"))
  } else{
    df_out = df
  }
  # Return data
  return(df_out)
}


#' Pull the data and run the CAViaR function on it
#'
#' @param input_data - data to use in the function
#' @param range_data - range of the data to use
#'
#' @return - a list of values from the caviar function
#' @export
#'
#' @examples - caviar_pull(spy)
caviar_pull = function(input_data, range_data = (2:dim(input_data)[1])){
  # Run the caviar data
  caviar <- caviarOptim(input_data[range_data,2])
  return(caviar)
}

#' Function for producing rolling predictions
#' Model 1 = Symmetric Absolute Value, 2 = Asymmetric slope, 3 = Indirect GARCH, 4 = Adaptive
#'
#' @param input_data - input data from the previous function
#' @param range_data - range of the data to consider
#' @param nfcst - number of forecasts to make
#' @param model - model to use (integers 1 through 4). Defaults to 1. 
#' @param level - level of significance to use.
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - an xts object which contains rolling CAViaR predictions
#' @export
#'
#' @examples - rolling_predictions(spy, nfcst = 22)
rolling_predictions = function(input_data, range_data = (2:dim(input_data)[1]), nfcst = 250, model =1, level = 0.01, G = 5, col = 2){
  # Run the varpredict function
  varpredict <- rollapplyr(input_data[range_data,col], length(range_data) - nfcst, caviarOptim, model, level, predict = 1, k = G) %>% lag
  # Eliminate NAs
  # pred_no_na = na.omit(varpredict)
  # Return the data
  # return(pred_no_na)
  return(varpredict)
}

#' Function to Calculate Loss from the above predictions
#'
#' @param symbol - symbol to work with from quantmod. Must be in quotations to work
#' @param start_dt - start date of the data to build the forecast on 
#' @param end_dt - end date of the data to build the forecast on  
#' @param nfcst - number of data points to use in the forecast
#' @param model - model to use. Defaults to 1
#' @param level - level of significance. Defaults to 1%
#' @param G - argument for the k parameter in the 4th model (adaptive). Default is 5
#'
#' @return - loss using absolute value
#' @export - a plot of the data
#'
#' @examples
loss_calc_uv = function(symbol, start_dt, end_dt, nfcst, model = 1, level = 0.01, G = 5){
  # Pull in the data
  raw_data = data_pull(symbol, start_date = start_dt, end_date = end_dt)
  # Forecast based on the data
  fcst = na.omit(rolling_predictions(raw_data, nfcst = nfcst, model = model, level = level, G = G))*(-1)
  # Extract actuals
  act = tail(raw_data, n = nfcst)[,2]
  # Join the two together and rename
  join = merge(fcst,act,all=TRUE)
  colnames(join) <- c("Fcst_VaR", "Act_Return")
  # print(join)
  # Calculate the losses
  loss = abs(sum(ifelse(act > fcst, level, (-1)*(1-level))))
  # Plot the data
  plot = plot.xts(join, col = c("red", "black"), lty = c(2,1), main = "Log Return from the SPY vs. Fcst. VaR",grid.col = NA, legend.loc = "bottomleft")
  return(list(loss, plot, act, fcst))
}

#' This is a function which creates a data frame for the response and explanatory variables that we'll feed into the diffusion index
#'
#' @param symbol_list - a list of symbols recognizable by the 
#' @param resp_var - the response variable we'd like to forecast; default is SPY
#' @param compl_case - defaults to true...only includes complete cases in the data
#' @param adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param resp_adj_close - use adjusted closing prices for the explanatory variables? default is 1 for YES
#' @param start_date - starting data to use
#' @param end_date - ending date of the data
#' @param lag_pred - do we lag the predictions? It is STRONGLY recommended that this is 0
#'
#' @return - a data frame which can be fed into the SWfore function
#' @export
#'
#' @examples - diff_index_df(c("XLF", "XLE", "PSCT", "XLV", "VPU", "XLP", "IGF", "XWEB", "PPTY"))
diff_index_df = function(symbol_list, resp_var = "SPY", compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), lag_pred = 1){
  # Pull in response variable
  response_pull = getSymbols(resp_var, auto.assign = FALSE, from = start_date, to = end_date)
  # Get adjusted closing price
  if (resp_adj_close == TRUE){
    diff_df = Ad(response_pull)
  } else {
    diff_df = Cl(response_pull)
  }
  # Loop through the symbols and join in data
  for (i in 1:length(symbol_list)){
    # Pull closing price
    expl_pull = getSymbols(symbol_list[i], auto.assign = FALSE, from = start_date, to = end_date)
    # Extract closing price - 4th element
    if (adj_close == TRUE){
      expl_cl = Ad(expl_pull)
    } else {
      expl_cl = Cl(expl_pull)
    }
    # New code for 4.16.2020 - lag the explanatory variables
    if (lag_pred == TRUE){
      # Lag the explanatory variables by 1
      lag_exp = lag(expl_cl, 1)
      # Append the first lag to the data frame
      diff_df = merge(diff_df, lag_exp, join = "left", fill = NA)
    } else{
      # Return the data frame without lags
      diff_df = merge(diff_df, expl_cl, join = "left", fill = NA)
    }
  }
  if (lag_pred == TRUE){
    # Chop off the first row
    diff_df = diff_df[-1,]
  }
  else {
    print("PLEASE NOTE - the explanatory variables in this DF are NOT lagged. Be careful to avoid look-ahead bias!")
  }
  # Return complete cases only 
  if (compl_case == TRUE){
    diff_df_out = diff_df[complete.cases(diff_df), ]
  } else{
    diff_df_out = diff_df
  }
  
  return(diff_df_out)
}

#' Converts a diff_df into a data frame with approximate percentage changes diff(log(diff_df))
#'
#' @param diff_df - output of the diff_index_df function with complete cases
#'
#' @return - retuns the differenced data
#' @export
#'
#' @examples - pc_diff_index(test_compl) 

pc_diff_index = function(diff_df){
  # Difference the log of the data
  pc_diff_index = diff(log(diff_df))
  # Remove the first row
  pc_diff_index_out = pc_diff_index[-1,]
  return(pc_diff_index_out)
}

#' Below is the modified diffusion index code.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param end - specifies an alternate ending value
#' @param print_mdl - print the model summary and the MSE
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di = function (y, x, orig, m, tau, end = NULL, print_mdl = 0) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Apply the linear model - HERE is the key.
  # mm = lm(y1 ~ DF) - old function
  mm = rq(y1 ~ DF, tau = tau)
  # Print the data
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix
  coef = matrix(mm$coefficients, (m + 1), 1)
  # Initializes yhat variables and MSE
  yhat = NULL
  MSE = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+1) matrix
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, 
        ])
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    err = y[(orig + 1):nT] - yhat
    MSE = mean(err^2)
    if (print_mdl == 1){
      cat("MSE of out-of-sample forecasts: ", MSE, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, MSE = MSE, loadings = M1, 
      DFindex = Dindex)
}

#' Below is the modified diffusion index code to include lagged variables.
#'
#' @param y - response variable
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param m - number of diffusion indexes used
#' @param tau - VaR level to use; must be between 0 and 1
#' @param ar_tf - AR transformation type. (1 - no transformation,
#' 2 - absolute value, 3 - asymmetric slope)
#' @param p - number of AR lags to include. Default is one.
#' @param print_mdl - option to print the model summary to make sure everytning is ok. 0 is default.
#' @param model - model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
#'
#' @return - returns a list of variables for use in the diffusion index
#' @export
#'
#' @examples
mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL) 
{
  # Converts the response variables into a matrix
  if (!is.matrix(x)) 
      x = as.matrix(x)
  # nT is number of t time-steps
  nT = dim(x)[1]
  # Add a line to establish the number of data points used in the test.
  if (is.null(end) != TRUE){
    nT = end
  }
  # k is the number of diffusion indices used
  k = dim(x)[2]
  # Sanity checks to ensure that the origin isn't past the number of time points
  if (orig > nT) 
      orig = nT
  # Makes sure that there aren't more predictors than there variables in the dataset
  if (m > k) 
      m = k
  # Makes sure there are at least some variables
  if (m < 1) 
      m = 1
  # Subdivides the dataframe
  x1 = x[1:orig, ]
  # Calculates means of each row
  me = apply(x1, 2, mean)
  # Calculates standard deviations of each column
  se = sqrt(apply(x1, 2, var))
  # Creates a matrix x1, which normalizes all the columns. 
  # This may be an issue since it assumes that the distribution is sufficiently described by the first two moments
  x1 = x
  for (i in 1:k) {
      x1[, i] = (x1[, i] - me[i])/se[i]
  }
  V1 = cov(x1[1:orig, ])
  # Performs an eigen decomposition
  m1 = eigen(V1)
  # Selects eigenvalues
  sdev = m1$values
  # Selects eigenvectors
  M = m1$vectors
  # Makes a smaller matrix
  M1 = M[, 1:m]
  # This is the diffusion index model - [orig x p]*[p x m] = [orig x m]
  Dindex = x1 %*% M1
  # Cut down both the response and predictors to be a reasonable size
  y1 = y[1:orig]
  DF = Dindex[1:orig, ]
  # Copy the data frame
  DF_wl = Dindex
  # Lag the y-variable
  for (i in 1:p){
    # Create a lagged variable
    lag_var = lag(y, i)
    # Append the first lag to the data frame
    DF_wl = cbind(DF_wl,lag_var)
  }
  # Identify the right columns
  l_ar = ncol(DF_wl)
  f_ar = l_ar - p + 1
  # Keep the last columns kept to the side
  all_lag = DF_wl[,(f_ar:l_ar)]
  # Cut off the first row to avoid NA's
  DF_trim = DF_wl[1:orig,]
  # Rename the columns
  # Here's the new function with an untransformed AR(p) lag
  if (ar_tf == 1){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an SAV AR(p) lag
  if (ar_tf == 2){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], abs(DF_trim[-(1:p),(f_ar:l_ar)]))
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
  }
  # Here's the new function with an asymmetric slope for the AR(1) lag
  # Indicator; 0 if percent change is negative, 1 if it's positive
  # indi = ifelse(DF_trim[,ar] < 0, 0, 1)
  if (ar_tf == 3){
    # Create a matrix of indicators
    indi_mat = matrix(0, nrow(DF_wl), p)
    # Generalize the above code
    for (i in 1:p){
      # Populate the indicator
      indi_mat[,i] = ifelse(DF_wl[,f_ar + i - 1] < 0, 0, 1)
    }
  }
  # Fitting the regression
  if (ar_tf == 3){
    # Incorporate everything in to an input data frame
    df_in = cbind(y1[-(1:p)], DF_trim[-(1:p),-(f_ar:l_ar)], DF_trim[-(1:p),(f_ar:l_ar)], indi_mat[((p+1):orig),])
    # Rename the columns
    # Initialize a character vector
    nvec = c(rep(0, 1+m+2*p))
    # Populate the vector - first value is the response
    nvec[1] <- names(y)
    # Next are the diffusion indices
    for (i in 1:m){
      nvec[i+1] = paste0("Diff_Index_", i)
    }
    # Next are the lagged variables
    for (i in 1:p){
      nvec[i+1+m] = paste0("Lag_", i)
    }
    # Last are the positive indicator variables
    for (i in 1:p){
      nvec[i+1+m+p] = paste0("Pos_Val_for_Lag_", i)
    }
    # Assign the names. Note that this is a matrix
    names(df_in) <- nvec
    # Run the model
    mm = rq(df_in[,1] ~ df_in[,-1], tau = tau)
    # mm = rq(y1[-(1:p)] ~ DF_trim[-(1:p),-(f_ar:l_ar)] + DF_trim[-(1:p),(f_ar:l_ar)] + indi_mat[((p+1):orig),], tau = tau)
    # Add a different line to account for the indicator variable
    # intercept + m + 2*nlag to account for the number of indicator variables
    coef = matrix(mm$coefficients, (1 + m + 2*p), 1)
  }
  if (print_mdl == 1){
    print(summary(mm))
  }
  # Puts coefficients in a matrix - added the AR terms
  # coef = matrix(mm$coefficients, (m + 1), 1)
  if (ar_tf != 3){
    coef = matrix(mm$coefficients, (1 + m + p), 1)
  }
  # Initializes yhat variables and MSE
  yhat = NULL
  loss = NULL
  if (orig < nT) {
    # Creates a nfcst by (m+2) matrix
    # Add on the lagged variables
    newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,])
    # Incorporate lagged variables
    if (ar_tf == 3){
      newx = cbind(rep(1, (nT - orig)), Dindex[(orig + 1):nT, ], all_lag[(orig+1):nT,], indi_mat[(orig+1):nT,])
    }
    # [nfcstx(m+1)]*[(m+1)x1] = [nfcstx1]
    yhat = newx %*% coef
    # Calculates errors
    loss = abs(sum(ifelse(y[(orig + 1):nT] > yhat, tau, (-1)*(1-tau))))
    # Modifying this part to only print this if specified
    if (print_mdl == 1){
      cat("Losses of out-of-sample forecasts: ", loss, "\n")
    }
  }
  SWfore <- list(coef = coef, yhat = yhat, loss = loss, loadings = M1, 
      DFindex = Dindex, name_vector = nvec)
}

# Decide on the optimal number of vectors.

# (y, x, orig, m, tau) 

#' Function that calculates loss over a given period of time for the diffusion index model
#'
#' @param y - response variables
#' @param x - explanatory variable
#' @param orig - forecast origin
#' @param end - forecasting ending. Note: as the function is currently written on 2/24, this option doesn't do anything.
#' @param m - number of diffusion indices to use
#' @param tau - VaR level
#' @param mod_di - use the modified DI?
#'
#' @return - returns a list of the loss sum and the loss vector
#' @export
#'
#' @examples - loss_calc(pc_df[,1], pc_df[,-1], 757, 1027, 1, 0.01)
loss_calc = function(y, x, orig, m, tau, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, end = NULL){
  # Extract y_hat values
  if (mod_di == 0){
    di = mod_di(y=y,x=x,orig=orig,m=m, tau=tau, end = end, print_mdl = print_mdl)
  }
  else {
    di = mod_di_wl(y=y,x=x,orig=orig,m=m, tau=tau, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model, end = end)
  }
  # mod_di_wl = function (y, x, orig, m, tau, ar_tf = 1, p = 1, print_mdl = 0, model = 1)
  yhat = di$yhat[1:(end-orig)]
  # Calculate the loss
  # Initialize loss vector
  lvec = rep(0,(end-orig))
  # Take the difference
  for (i in 1:(end-orig)){
    # Calculate an indicator variable
    ind = ifelse(y[orig+i] < yhat[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - ind)*(y[orig+i] - yhat[i])
  }
  # Add up the losses - change to look at sum of losses. Won't change decision criterion
  sumloss = sum(lvec)
  # sumloss = sum(lvec)/length(lvec)
  return(list(sumloss,lvec))
}


#' Function that selects the optimal number of predictors
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_m(pc_df[,1], pc_df[,-1], 757, 1027, 0.01, low_m =1, high_m  = 5)
opt_m = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, mod_di = 0, ar_tf = 1, p = 1, print_mdl = 0, model = 1, rowname = NULL){
  # Initialize a loss vector
  loss_vec = rep(0,high_m-low_m + 1)
  # Initialize an m vector
  m_vec = seq(low_m, high_m, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:length(loss_vec)){
    loss_vec[i] = quiet(loss_calc(y=y,x=x,orig=orig,end=end, m = m_vec[i], tau = tau, mod_di = mod_di, ar_tf = ar_tf, p = p, print_mdl = print_mdl, model = model))[[1]]
  }
  # Find the minimizer
  opt_m = which.min(loss_vec)
  opt_p = NA
  # Combine into a data frame
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    # Write the row names
    rownames(df) <- c("MV CAViaR")
  }
  else {
    rownames(df) <- rowname
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, loss_vec, df))
}
#' Function that selects the optimal number of lags
#'
#' @param y - response vector
#' @param x - predictor variables
#' @param orig - forecast origin
#' @param end - ending of validation set
#' @param tau - VaR in question
#' @param low_m - low value of m to consider
#' @param high_m - high value of m to consider
#'
#' @return - returns the optimal value of m
#' @export
#'
#' @examples - opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = 757, end = 1007, tau = 0.01, low_m =1, high_m  = 5, low_p = 1, high_p = 10, ar_tf = 2, mod_di = 1)
opt_mp = function(y, x, orig, end = NULL, tau, low_m = 1, high_m, low_p = 1, high_p, mod_di = 0, ar_tf = 1, print_mdl = 0, model = 1, print_mp = 0, rowname = NULL){
  # Initialize a loss matrix
  loss_mat = matrix(0, high_p-low_p + 1,high_m-low_m + 1)
  # Initialize a p vector
  p_vec = seq(low_p, high_p, by = 1)
  # Loop through and populate the loss vector
  for (i in 1:nrow(loss_mat)){
    loss_mat[i,] = opt_m(y = y, x = x, orig = orig, end = end, tau = tau, low_m = low_m, high_m  = high_m, p = i, mod_di = mod_di, ar_tf = ar_tf, print_mdl = print_mdl, model = model)[[2]]
  }
  # Find the minimizer
  opt_p = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,1]
  opt_m = which(loss_mat == min(loss_mat), arr.ind = TRUE)[1,2]
  # Print the optimal p and optimal m
  df = as.data.frame(cbind(opt_m, opt_p))
  names(df) <- c("Optimal m", "Optimal p")
  # Assign a rowname
  if (is.null(rowname) == TRUE){
    if (ar_tf == 1){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AR")
    } else if (ar_tf == 2){
      # Write the row names
      rownames(df) <- c("MV CAViaR + SAV")
    } else if (ar_tf == 3){
      # Write the row names
      rownames(df) <- c("MV CAViaR + AS")
    } else {
      rownames(df) <- c("Unknown Model")
    }
  }
  else {
    rownames(df) <- rowname
  }
  # Print the df if the option is turned on
  if (print_mp == 1){
    print(df)
  }
  # Return the loss_vector and the minimzer
  return(list(opt_m, opt_p, loss_mat, df))
}
#' A function that combines optimal values of m and p into a final table
#'
#' @param m1 - the data frame from the "MV CAViaR" run
#' @param m2 - the data frame from the "MV CAViaR + AR" run
#' @param m3 - the data frame from the "MV CAViaR + SAV" run
#' @param m4 - the data frame from the "MV CAViaR + AS" run
#'
#' @return - a nicely formatted table
#' @export
#'
#' @examples - pretty_pm(opt_pred_nl[[3]], opt_pm_m1[[4]], opt_pm_m2[[4]], opt_pm_m3[[4]])
pretty_pm = function(m1, m2, m3, m4){
  # Merge the individual data frames
  pm_pretty_df = rbind(m1, m2, m3, m4)
  # Format nicely
  pm_pretty_df %>% kable(caption = "Optimal Number of Diffusion Indices (m) and Lags (p) for Different Models", digits = 0) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = "The MV CAViaR model doesn't have an optimal value for p because there are no AR lags in the model"
  )
  
}

#' Here is a function that runs the univariate CAViaR model 4 times
#'
#' @param df - the percent change data frame to consider
#' @param nfcst - number of forecasts to run
#' @param tau - the VaR level to consider
#' @param no_run - specifies if any models should not be run
#'
#' @return - a list of the 4 univariate model forecasts
#' @export
#'
#' @examples - aceg = gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
  # Initialize a list  
  out_list = list()
  # Run the four models - model 1; SAV
  if (no_run[1] == 0){
    uvcav_1 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 1, G = 10, col = 1, level = tau)
  }
  # Add a filler if there's no entry
  else {
    uvcav_1 = 0
  }
  # Model 2 - AS
  if (no_run[2] == 0){
    uvcav_2 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 2, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_2 = 0
  }
  # Model 3 - GARCH
  if (no_run[3] == 0){
    uvcav_3 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 3, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_3 = 0
  }
  # Model 4 - Adaptive
  if (no_run[4] == 0){
    uvcav_4 = rolling_predictions(df[,1], range_data = (1:length(df[,1])), nfcst = nfcst, model = 4, G = 10, col = 1, level = tau)
  }
  else {
    uvcav_4 = 0
  }
  # Export the data as a list
  return(list(uvcav_1, uvcav_2, uvcav_3, uvcav_4))
}

#' Function to plot the data which we generate in previous functions
#'
#' @param plot_matrix - matrix with the data to plot
#' @param norm_value - what to subtact from the data to make it on a percentage change basis. Default is 100.
#'
#' @return 
#' @export - a plot of the data by diffusion index number
#'
#' @examples = plt_data(plot_mtx[[1]]), abc = plt_data(plot_mat, tau = 0.01)
plt_data = function(plot_matrix, tau, resp_var, ntest){
  # Establish a maximum and minimum value
  max_val = max(plot_matrix[,1:ncol(plot_matrix)])
  min_val = min(plot_matrix[,1:ncol(plot_matrix)])
  # Calculate inital and ending time value
  start = index(plot_matrix)[1]
  end = index(plot_matrix)[nrow(plot_matrix)]
  ind_vals = index(plot_matrix) - start
  # Create an initial plot and add lines
    for (i in 1:ncol(plot_matrix)){
      if (i == 1){
        # 4/2/2020 - fixing the index
        plot.ts(ind_vals,plot_matrix[,i], type = "l", xlab = paste("Days Since", as.Date(start)), ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = paste("Predicting", resp_var, "Returns from", as.Date(start), "to", as.Date(end)), sub = paste("The VaR Level is ", 100*tau, "%", "; There are ", ntest, " Trading Days Plotted Above", sep = ""))
        # plot.ts(index(plot_matrix), plot_matrix[,i], type = "l", xlab = "Trading Days", ylab = "Percent Change in PG", ylim = c(min_val,max_val), lwd = 1, main = "Predicting PG Returns Over Last 250 Trading Days in 2008", sub = paste("The VaR Level is ", 100*tau, "%", sep = ""))
    } else if(i %in% seq(2,8,1)) {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2)
    } else {
        lines(ind_vals,plot_matrix[,i], col = i-1, lty = 2, lwd = 2)
    }
    }
  # Define a sequence for plotting
  plot_seq = seq(1, ncol(plot_matrix))
  legend("topleft", legend = c(colnames(plot_matrix)), col = plot_seq, lty = c(1, rep(2, 7), rep(3, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))), lwd = c(1, rep(1, 7), rep(2, ifelse(ncol(plot_matrix)-8 <= 0, 0, ncol(plot_matrix)-8))))
  # Add a line for 0
  # abline(h = 0, col = "black", lty = 2)
}


#' A function to calculate losses based on the test sample
#'
#' @param true_vec - the true vector of returns
#' @param pred_vec - the predicted vector from the model runs
#' @param tau - VaR level. Must match what the model used
#'
#' @return - total losses and the entire loss vector
#' @export
#'
#' @examples
loss_test = function(true_vec, pred_vec, tau){
  # Initialize a loss vector
  lvec = rep(0, length(true_vec))
  # Initialize a break vector to see when VaR is broken
  bvec = rep(0, length(true_vec))
  for (i in 1:length(true_vec)){
    # Calculate an indicator variable
    bvec[i] = ifelse(true_vec[i] < pred_vec[i], 1,0)
    # Use indicator in function below
    lvec[i] = (tau - bvec[i])*(true_vec[i] - pred_vec[i])
  }
  # Add up the losses
  # sumloss = sum(lvec)/length(lvec)
  sumloss = sum(lvec)
  # Add up the VaR breakage
  varbreak = sum(bvec)/length(bvec)
  return(list(sumloss,lvec, varbreak, bvec))
}
#' A function to calculate losses based on the plot matrix
#'
#' @param data_mat - a matrix of forecasted VaR values, with the true value in the first column
#' @param tau - VaR level. Must match what the model used
#'
#' @return - a list of four items. 
#' 1 = a vector of the losses of all models. 
#' 2 = a vector showing the percentage of VaR breaks by model
#' 3 = the loss matrix
#' 4 = the break matrix
#' @export
#'
#' @examples
gen_loss_test = function(data_mat, tau){
  # Initialize loss and break matrices
  lmat = bmat = matrix(0, nrow = nrow(data_mat), ncol = ncol(data_mat)-1)
  # bvec = rep(0, length(true_vec))
  # Populate the matrices
  for (i in 1:nrow(lmat)){
    for (j in 1:(ncol(lmat))){
      # Calculate an indicator variable
      bmat[i,j] = ifelse(data_mat[i,1] < data_mat[i,j+1], 1,0)
      # Use indicator in function below
      lmat[i,j] = (tau - bmat[i,j])*(data_mat[i,1] - data_mat[i,j+1])
    }    
  }
  # Add up the losses
  sumloss = colSums(lmat)
  # Add up the VaR breakage
  varbreak = colSums(bmat)/nrow(bmat)
  return(list(sumloss, varbreak, lmat, bmat))
}
#' A function to make a nice comparison of losses
#'
#' @param data_mat - input data matrix used in the calculation of losses
#' @param loss_list - a list of the losses calculated from the CAViaR function
#' @param tau - the risk level used
#' @param ntest - the number of test points
#'
#' @return
#' @export - returns a nicely formatted table
#'
#' @examples - pretty_tables(plot_mat, l_list, tau = 0.01)
pretty_tables = function(data_mat, loss_list, tau, ntest){
  # Combine into a data frame
  df = as.data.frame(rbind(loss_list[[1]], loss_list[[2]]))
  # Calculate inital and ending time value
  start = index(data_mat)[1]
  end = index(data_mat)[nrow(data_mat)]
  # Add row/column names
  colnames(df) <- colnames(data_mat[,-1])
  rownames(df) <- c("Losses", "VaR Breaks (%)")
  # Convert to a table
  df %>% kable(caption = paste("Comparison of VaR Methods for a ", tau*100, "% VaR", sep = ""), digits = 3) %>% kable_styling("striped", full_width = F) %>% kable_styling() %>% footnote(general = paste("Calculated using", ntest, "trading days from", as.Date(start), "to", as.Date(end)))
}
#' A dressed up version of the export function
#'
#' @param var_file - file to export
#' @param path - filepath
#' @param filename - name of the file, ending with .CSV
#'
#' @return
#' @export - exported CSV file
#'
#' @examples - exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")
exp_func = function(var_file, path, filename){
  # Write a zoo
  write.zoo(var_file, paste0(path, filename), quote = FALSE, sep = ",")
}

# exp_func(var_file = var_1pc_2016_usetf[[1]], path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "TEST.csv")

#' This is the "master" function where we'll evaluate the importance of the VaR model over several time periods
#'
#' @param symbol_list - a list of symbols to feed into the model 
#' @param resp_var - the response variable
#' @param compl_case - should the model require complete cases? Default value is 1.
#' @param adj_close - use adjusted close price for the predictors? Default value is 1.
#' @param resp_adj_close - use adjusted close price for the response? Default value is 1.
#' @param start_date - start date to pull data from
#' @param end_date - end date to pull data from
#' @param nval - number of validation points to use
#' @param ntest - number of test points to use
#' @param tau - VaR level to use
#' @param low_m - low number of predictors to test
#' @param high_m  - low number of predictors to test
#' @param uv_list - a list of a pre-run univariate model. If a data frame is not provided, the lengthy uv model will run 
#' @param no_run - things not to run in the model
#' @param low_p - low value for number of lags
#' @param high_p - high value for number of lags
#' @param na_interp - should the function interpolate NA's
#' @param print_mdl - print the model summaries?
#' @param print_mp - print the optimal values for p and m
#' @param lag_pred - do you want to lag the m predictors (default is 1; strongly recommended)
#' @param rowname - what to name the rows of the nice p and m matrix
#' @param export_csv - do you want to export a CSV? Default is 1.
#' @param path - path to export the CSV
#' @param filename - what to name the CSV
#'
#' @return - a list of the plot matrix, a plot, a list with losses, and a table
#' @export - a plot and a table
#'
#' @examples - cav_simul(c("DIS", "GE", "IBM", "MMM", "XOM"), resp_var = "PG", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 5, tau = 0.01, uv_list = uv_cav_list)
cav_simul = function(symbol_list, resp_var, compl_case = 1, adj_close = 1, resp_adj_close = 1, start_date = "1900-01-01", end_date = Sys.Date(), nval, ntest, tau, low_m = 1, high_m, low_p = 1, high_p, uv_list = NULL, no_run = c(0,0,0,0), na_interp = TRUE, print_mdl = 0, print_mp = 0, lag_pred = 1, rowname = NULL, export_csv = 1, path, filename){
  # Select data parameters, pull the data, and percent change the data
  df = diff_index_df(symbol_list = symbol_list, resp_var = resp_var, compl_case = compl_case, adj_close = adj_close, resp_adj_close = resp_adj_close, start_date = start_date, end_date = end_date, lag_pred = lag_pred)
  # Take the percent change of the data
  pc_df = pc_diff_index(df)
  # Extract the legnth of the data frame
  nr = test_end = nrow(pc_df)
  # Calculate the start of the val period, the end of the val period, and the beginning and end of test period
  test_orig = test_end - ntest
  val_end = test_orig
  val_orig = test_orig - nval
  # Test for the optimal number of parameters
  opt_pred_nl = opt_m(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, rowname = rowname)
  opt_pred_art1 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 1, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art2 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p,mod_di = 1, ar_tf = 2, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  opt_pred_art3 = opt_mp(y = pc_df[,1], x = pc_df[,-1], orig = val_orig, end = val_end, tau = tau, low_m = low_m, high_m = high_m, low_p = low_p, high_p = high_p, mod_di = 1, ar_tf = 3, print_mdl = print_mdl, print_mp = print_mp, rowname = rowname)
  # gen_uv_test(pc_df, 1, 0.05, no_run = c(1,1,0,1))
  # Use the above forecasts to input into the above
  mv_fcst = mod_di(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_nl[[1]], tau = tau, print_mdl = print_mdl)
  mv_fcst_art1 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art1[[1]], p = opt_pred_art1[[2]], tau = tau, ar_tf = 1, print_mdl = print_mdl)
  mv_fcst_art2 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art2[[1]], p = opt_pred_art2[[2]], tau = tau, ar_tf = 2, print_mdl = print_mdl)
  mv_fcst_art3 = mod_di_wl(pc_df[,1], pc_df[,-1], orig = test_orig, m = opt_pred_art3[[1]], p = opt_pred_art3[[2]], tau = tau, ar_tf = 3, print_mdl = print_mdl)
  # Calculate the number of predictions
  if (is.null(uv_list) == TRUE){
    # Print a warning
    print("WARNING: Not supplying an input data frame will require this function to run for a significant amount of time (1hr+)")
    # Call the function
    # gen_uv_test = function(df, nfcst, tau, no_run = c(0,0,0,0)){
    # print(head(pc_df))
    uv_list = gen_uv_test(df = pc_df, nfcst = ntest, tau = tau, no_run = no_run)
    # Add to a data frame
    # Incorporate the rolling predictions function results here
  plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list[[1]][(test_orig+1):test_end]*(-1), uv_list[[2]][(test_orig+1):test_end]*(-1), uv_list[[3]][(test_orig+1):test_end]*(-1), uv_list[[4]][(test_orig+1):test_end]*(-1))
  } else {
    # Assign the columns of the data frame
    # head(var_5pc_2010_usetf[[1]][,6:9])
    # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE) 
    # test_df = head(var_5pc_2010_usetf[[1]][,6:9])
    # test_df$SAV
    # test_df$`Abs. Slope`
    # test_df$`Ind. GARCH`
    # test_df$Adaptive
    plot_mat = cbind(pc_df[(test_orig+1):nrow(pc_df),1], mv_fcst$yhat[1:ntest], mv_fcst_art1$yhat[1:ntest], mv_fcst_art2$yhat[1:ntest], mv_fcst_art3$yhat[1:ntest], uv_list$SAV, uv_list$`Abs. Slope`, uv_list$`Ind. GARCH`, uv_list$Adaptive)
  }
  # Count the NAs and print a warning
  print(paste("NOTE: There are ", sum(is.na(plot_mat)), " NA(s) in the dataset", sep = ""))
  # Linearly interpolate the NAs
  if (na_interp == TRUE){
    # Assign the plot matrix to a new value
    plot_mat_na <- plot_mat
    # Print a warning
    print("WARNING: There were missing values in the plot matrix.")
    # Interpolate the NA's
    for (i in 1:ncol(plot_mat_na)){
      # Interpolate the data
      plot_mat[,i] <- na.approx(plot_mat_na[,i])
    }
  }
  # model type (1 - SAV, 2 - AS, 3 - GARCH, 4 - ADAPTIVE)
  # Add descriptive titles onto the plot_mat
  colnames(plot_mat) <- c(resp_var, "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # colnames(plot_mat) <- c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")
  # Plot everything
  plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  tables = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Run the function for optimal p and m
  pm_table = pretty_pm(opt_pred_nl[[3]], opt_pred_art1[[4]], opt_pred_art2[[4]], opt_pred_art3[[4]])
  # Export the matrix
  if (export_csv == 1){
    exp_func(var_file = plot_mat, path, filename)
  }
  # Print the tables and the plot
  print(plot)
  print(tables)
  print(pm_table)
  return(list(plot_mat, plot, l_list, tables, plot_mat_na, pm_table))
}
#' A function to input the VaR files, plot them and generate tables
#'
#' @param file_path - file path to use
#' @param filename - name of the file
#' @param tau - quantile to use
#' @param resp_var - response variable to use in the plot
#' @param ntest - number of test points
#' @param cn_input - column name inputs
#'
#' @return - a list of the xts file, the plot, the loss list, and tables
#' @export - a plot and tables
#'
#' @examples - test = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)
var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "M1", "M2", "M3", "M4", "M5", "M6", "M7", "M8")){
# var_input_disp = function(file_path, filename, tau, resp_var = "SPY", ntest = 250, cn_input = c("SPY", "MV CAViaR", "MV CAViaR + AR", "MV CAViaR + SAV", "MV CAViaR + AS", "SAV", "Abs. Slope", "Ind. GARCH", "Adaptive")){
  # Import data
  plot_mat = read.csv(paste0(file_path,filename), sep = ",", header = T, stringsAsFactors = FALSE)
  # Fix date format
  plot_mat$Index = as.Date(plot_mat$Index)
  # Convert to an xts
  plot_mat = xts(plot_mat[,-1], order.by = plot_mat[,1])
  # Fix column names
  colnames(plot_mat) <- cn_input
  # Plot everything
  plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # plot = plt_data(plot_mat, tau = tau, resp_var = resp_var, ntest = ntest)
  # Calculate losses
  l_list = gen_loss_test(plot_mat, tau = tau)
  # Put into tables
  pm_table = pretty_tables(plot_mat, l_list, tau = tau, ntest = ntest)
  # Print the tables and the plot
  # print(plot)
  # print(tables)
  print(pm_table)
  # Return the xts, the plot, the loss list, and the tables
  return(list(plot_mat))
  # return(list(plot_mat, plot, l_list, tables))
}
# return(list(plot_mat, plot, l_list, tables))

# Call the above function
v1_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2008_us_etf.csv", 0.01)
# pretty_tables(v1_2008_usetf[[1]], v1_2008_usetf[[3]], tau = 0.01, ntest = 250)
v5_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2008_us_etf.csv", 0.05)
v10_2008_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2008_us_etf.csv", 0.10)

# head(v10_2008_usetf[[1]])
# v10_2008_usetf
# 1%, 5%, 10% VaR - 2008 - 1st set of predictors
# var_1pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2008_us_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2008_us_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2008_us_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2008_glob_etf.csv", 0.01)
v5_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2008_glob_etf.csv", 0.05)
v10_2008_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2008_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2008 - 2nd set of predictors
# var_1pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2008_glob_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2008_glob_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2008_glob_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# 1%, 5%, 10% VaR - 2008 - 3rd set of predictors
# var_1pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2008_comm_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2008_comm_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2008_comm_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2008_bond_etf.csv", 0.01)
v5_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2008_bond_etf.csv", 0.05)
v10_2008_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2008_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2008 - 4th set of predictors
# var_1pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2008_bond_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2008_bond_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2008_bond_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2008_all_etf.csv", 0.01)
v5_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2008_all_etf.csv", 0.05)
v10_2008_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2008_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2008 - 5th set of predictors
# var_1pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2008_all_etf.csv", uv_list = var_1pc_2008_usetf[[1]])

# var_5pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2008_all_etf.csv", uv_list = var_5pc_2008_usetf[[1]])

# var_10pc_2008_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2004-01-01", end_date = "2008-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2008_all_etf.csv", uv_list = var_10pc_2008_usetf[[1]])
# Call the above function
v1_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2010_us_etf.csv", 0.01)
v5_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2010_us_etf.csv", 0.05)
v10_2010_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2010_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 1st set of predictors
# var_1pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2010_us_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2010_us_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2010_us_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2010_glob_etf.csv", 0.01)
v5_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2010_glob_etf.csv", 0.05)
v10_2010_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2010_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 2nd set of predictors
# var_1pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2010_glob_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2010_glob_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2010_glob_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# 1%, 5%, 10% VaR - 2010 - 3rd set of predictors
# var_1pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2010_comm_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2010_comm_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2010_comm_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2010_bond_etf.csv", 0.01)
v5_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2010_bond_etf.csv", 0.05)
v10_2010_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2010_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2010 - 4th set of predictors
# var_1pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2010_bond_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2010_bond_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2010_bond_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2010_all_etf.csv", 0.01)
v5_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2010_all_etf.csv", 0.05)
v10_2010_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2010_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2010 - 5th set of predictors
# var_1pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2010_all_etf.csv", uv_list = var_1pc_2010_usetf[[1]])

# var_5pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2010_all_etf.csv", uv_list = var_5pc_2010_usetf[[1]])

# var_10pc_2010_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2006-01-01", end_date = "2010-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2010_all_etf.csv", uv_list = var_10pc_2010_usetf[[1]])
# Call the above function
v1_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2014_us_etf.csv", 0.01)
v5_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2014_us_etf.csv", 0.05)
v10_2014_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2014_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 1st set of predictors
# var_1pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2014_us_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2014_us_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2014_us_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2014_glob_etf.csv", 0.01)
v5_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2014_glob_etf.csv", 0.05)
v10_2014_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2014_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 2nd set of predictors
# var_1pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2014_glob_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2014_glob_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2014_glob_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# 1%, 5%, 10% VaR - 2014 - 3rd set of predictors
# var_1pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2014_comm_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2014_comm_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2014_comm_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2014_bond_etf.csv", 0.01)
v5_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2014_bond_etf.csv", 0.05)
v10_2014_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2014_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2014 - 4th set of predictors
# var_1pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2014_bond_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2014_bond_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2014_bond_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2014_all_etf.csv", 0.01)
v5_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2014_all_etf.csv", 0.05)
v10_2014_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2014_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2014 - 5th set of predictors
# var_1pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2014_all_etf.csv", uv_list = var_1pc_2014_usetf[[1]])

# var_5pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2014_all_etf.csv", uv_list = var_5pc_2014_usetf[[1]])

# var_10pc_2014_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2010-01-01", end_date = "2014-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2014_all_etf.csv", uv_list = var_10pc_2014_usetf[[1]])
# Call the above function
v1_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_1pc_2016_us_etf.csv", 0.01)
v5_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_5pc_2016_us_etf.csv", 0.05)
v10_2016_usetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/","var_10pc_2016_us_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 1st set of predictors
# var_1pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_1pc_2016_us_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_5pc_2016_us_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_us_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 9, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_US_ETF_runs/", filename = "var_10pc_2016_us_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_1pc_2016_glob_etf.csv", 0.01)
v5_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_5pc_2016_glob_etf.csv", 0.05)
v10_2016_globetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/","var_10pc_2016_glob_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 2nd set of predictors
# var_1pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_1pc_2016_glob_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_5pc_2016_glob_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_glob_etf = cav_simul(c("JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 10, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_glob_ETF_runs/", filename = "var_10pc_2016_glob_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# 1%, 5%, 10% VaR - 2016 - 3rd set of predictors
# var_1pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_1pc_2016_comm_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_5pc_2016_comm_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_comm_etf = cav_simul(c("DBA", "DBC", "DBE", "DBB"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_comm_ETF_runs/", filename = "var_10pc_2016_comm_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_1pc_2016_bond_etf.csv", 0.01)
v5_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_5pc_2016_bond_etf.csv", 0.05)
v10_2016_bondetf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/","var_10pc_2016_bond_etf.csv", 0.10)
# iShares 1-3 Year Treasury Bond Fund (SHY)
# iShares 7-10 Year Treasury Bond Fund (IEF)
# iShares 20+ Year Treasury Bond Fund (TLT)
# iShares iBoxx $ Investment Grade Corporate Bond ETF (LQD)

# 1%, 5%, 10% VaR - 2016 - 4th set of predictors
# var_1pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_1pc_2016_bond_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_5pc_2016_bond_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_bond_etf = cav_simul(c("SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 4, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_bond_ETF_runs/", filename = "var_10pc_2016_bond_etf.csv", uv_list = var_10pc_2016_usetf[[1]])
# Call the above function
v1_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_1pc_2016_all_etf.csv", 0.01)
v5_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_5pc_2016_all_etf.csv", 0.05)
v10_2016_alletf = var_input_disp("/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/","var_10pc_2016_all_etf.csv", 0.10)
# 1%, 5%, 10% VaR - 2016 - 5th set of predictors
# var_1pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10, tau = 0.01, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_1pc_2016_all_etf.csv", uv_list = var_1pc_2016_usetf[[1]])

# var_5pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.05, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_5pc_2016_all_etf.csv", uv_list = var_5pc_2016_usetf[[1]])

# var_10pc_2016_all_etf = cav_simul(c("XLU", "XLP", "XLV", "XLK", "XLY", "XLI", "XLF", "XLB", "XLE", "JXI", "KXI", "IXJ", "IXP", "IXN", "RXI", "EXI", "IXG", "MXI", "IXC", "SHY", "IEF", "TLT", "LQD"), resp_var = "SPY", start_date = "2012-01-01", end_date = "2016-12-31", nval = 250, ntest = 250, low_m = 1, high_m = 23, low_p = 1, high_p = 10,tau = 0.10, print_mdl = 1, print_mp = 1, path = "/Users/stevenmoen/Documents/GitHub/CAViaR_MS_thesis/Data_Export/SPY_all_ETF_runs/", filename = "var_10pc_2016_all_etf.csv", uv_list = var_10pc_2016_usetf[[1]])

Literature Cited

LS0tCnRpdGxlOiAiTXVsdGl2YXJpYXRlIENBVmlhUiIKc3VidGl0bGU6ICJBIE1vcmUgSW5zaWdodGZ1bCBBcHByb2FjaCB0byBSaXNrIE1vZGVsaW5nIgphdXRob3I6ICJTdGV2ZW4gTW9lbiIKZGF0ZTogIlRodXJzZGF5LCBBcHJpbCAzMHRoLCAyMDIwIgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAotLS0KCmBgYHtyIGdsb2JhbF9vcHRpb25zLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTgsIGZpZy5wYXRoPSdGaWdzLycsCiAgICAgICAgICAgICAgICAgICAgICBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZSA9IFRSVUUpCmBgYAoKIyBBYnN0cmFjdAoKVGhpcyBwYXBlciBidWlsZHMgdXBvbiBwcmV2aW91cyBsaXRlcmF0dXJlIGZvciBtb2RlbGluZyB2YWx1ZS1hdC1yaXNrIHF1YW50aWxlcyB0aGF0IHVzZXMgYW4gQVJNQS1zdHlsZSBhcHByb2FjaCBieSBhZGRpbmcgRVRGcyBhcyBleHBsYW5hdG9yeSB2YXJpYWJsZXMgdGhhdCBhcmUgY29tYmluZWQgaW50byBwcmluY2lwYWwgY29tcG9uZW50IHZlY3RvcnMgYXQgdGhlIGZvcmVjYXN0IG9yaWdpbi4gQnkgY29tYmluaW5nIHRoZXNlIHByaW5jaXBhbCBjb21wb25lbnQgdmVjdG9ycyBhbG9uZyB3aXRoIHZhcmlvdXMgdHJhbnNmb3JtYXRpb25zIG9mIGxhZ2dlZCBhdXRvcmVncmVzc2l2ZSByZXNwb25zZSB2YXJpYWJsZXMsIHNpbWlsYXIgcHJlZGljdGl2ZSBhY2N1cmFjeSBpcyBhY2hpZXZlZCAocmVsYXRpdmUgdG8gdGhlIHVuaXZhcmlhdGUgbW9kZWwpIGFuZCBhIGNsZWFyZXIgaW50ZXJwcmV0YXRpb24gaXMgZ2FpbmVkLiBJbiBmYWN0LCB0aGlzIHRoZXNpcyBwcm9wb3NlcyBhbiBhbGdvcml0aG0gdG8gZGV0ZWN0IGNoYW5nZXBvaW50cyBpbiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIHRoYXQgY291bGQgYmUgdXNlZCBhcyBhIG1lYW5zIHRvIG1lYXN1cmUgY2hhbmdlcG9pbnRzIGluIHRoZSBlY29ub215LiBbREVMRVRFIElGIFRIRSBDSEFOR0VQT0lOVCBBUkdVTUVOVCBET0VTTidUIE1BS0UgU0VOU0UuXQoKIyBCYWNrZ3JvdW5kIGFuZCBJbnRyb2R1Y3Rpb24KCgpXaGVuIG1vZGVsaW5nIGZpbmFuY2lhbCB0aW1lIHNlcmllcywgc2ltcGx5IGNvbnNpZGVyaW5nIHRoZSBtZWFuIGFuZCB0aGUgdmFyaWFuY2UgaXMgaW5zdWZmaWNpZW50LiBJbiBmYWN0LCBtb2RlbGluZyBhIDElIG9yIGEgNSUgcXVhbnRpbGUgb2YgZGFpbHkgcmV0dXJucyBpcyBhIHdheSB0byB1bmRlcnN0YW5kIHdoYXQgaGFwcGVucyBvbiB0aGUgd29yc3QgZGF5cyBhbmQgdG8gaGF2ZSBhIGNsZWFyZXIgcGljdHVyZSBvZiB3aGF0IG1pZ2h0IGhhcHBlbiBkdXJpbmcgYSBkb3dudHVybi4gSW5kZWVkLCBmaW5hbmNlIHRoZW9yeSBzdWdnZXN0cyB0aGF0IGEgcHJpbWFyeSByZWFzb24gd2h5IHRoZSBTJlA1MDAsIHdoaWNoIGlzIGEgbWFya2V0LWNhcGl0YWxpemF0aW9uIHdlaWdodGVkIGluZGV4IGNvbXBvc2VkIG9mIHRoZSA1MDAtbGFyZ2VzdCBwdWJsaWNseSB0cmFkZWQgY29tcGFuaWVzIGluIHRoZSBVbml0ZWQgU3RhdGVzLCBoYXMgZWFybmVkIDYuOCUgaW5mbGF0aW9uLWFkanVzdGVkIHByZS10YXggcmV0dXJuIHdpdGggZGl2aWRlbmQgcmVpbnZlc3RtZW50IGZyb20gSmFudWFyeSAxODcxIHRocm91Z2ggQXByaWwgMjAyMCAoQ0lURSkgaXMgYmVjYXVzZSBvZiB0aGUgcmlzayBvZiBhIHNpZ25pZmljYW50IGRvd250dXJuLiBLZXJyeSBQZWNodGVyIGF0IEZvcmJlcyBkZXNjcmliZXMgaXQgYXMgYSBwcmVtaXVtIGZvciB0aGUgZmFjdCB0aGF0ICJzdG9ja3MgYXJlIHJpc2tpZXIiIGFuZCAibW9yZSBwcm9uZSB0byBwcmljZSBmbHVjdHVhdGlvbnMgaW4gdGhlIHNob3J0IHJ1biIgY29tcGFyZWQgdG8gbG93ZXIgcmlzayBpbnZlc3RtZW50cy4gV2hpbGUgdGhlIGxvbmctcnVuIHBpY3R1cmUgb2Ygc3RvY2sgcmV0dXJucyBpcyBhIGJpdCBjbGVhcmVyLCB0aGUgc2hvcnQtcnVuIGlzIGEgaHVnZSBxdWVzdGlvbiAtIGFuIGludmVzdG1lbnQgbWFuYWdlciB1c2luZyBmaW5hbmNpYWwgbGV2ZXJhZ2UgdG8gbWFnbmlmeSByZXR1cm5zIChwb3NpdGl2ZSBvciBuZWdhdGl2ZSkgdGhhdCBjb3VsZCBsZWF2ZSB0aGVtIGluIGRpcmUgc3RyYWl0cyBpZiB0aGVpciBpbnZlc3RtZW50cyBmZWxsIHJhcGlkbHksIGRlc3BpdGUgYSBzb3VuZCBsb25nLXJ1biBzdHJhdGVneS4KCldoaWxlIHRoZXJlIGFyZSBvdGhlciB3YXlzIHRvIHVuZGVyc3RhbmQgYW5kIG1lYXN1cmUgZG93bnNpZGUgcmlzaywgYSBjb21tb25seSBhY2NlcHRlZCBtZWFucyBpcyB1c2luZyB2YWx1ZS1hdC1yaXNrIChWYVIpLiBUaGUgbWV0cmljIGlzIHVuZGVyc3Rvb2QgYXMgZm9sbG93czogYSBvbmUtZGF5IDElIFZhUiBvZiAtMSBtaWxsaW9uIGRvbGxhcnMgZm9yIGEgcG9ydGZvbGlvIG1lYW5zIHRoYXQgdGhlIHBvcnRmb2xpbyB3aWxsIGxvc2UgYXQgbGVhc3QgJDEgbWlsbGlvbiBvbiB0aGUgMSUgd29yc3QgdHJhZGluZyBkYXlzLiBBIG1ham9yIGFkdmFudGFnZSBvZiBWYVIgaXMgdGhhdCBpdCBkaXN0aWxscyBhIGRpc3RyaWJ1dGlvbiBvZiByZXR1cm5zIGludG8gb25lIG51bWJlci4gQXMgc3VjaCwgVmFSIGlzIG9mdGVuIHVzZWQgaW4gc3RyZXNzIHRlc3RpbmcgYnkgcmVndWxhdG9yeSBhZ2VuY2llcyBpbiB0aGUgVW5pdGVkIFN0YXRlcywgdGhlIFVuaXRlZCBLaW5nZG9tLCBhbmQgRXVyb3BlIChDSVRFKS4KCk1hbnkgb2YgdGhlIGFwcHJvYWNoZXMgZm9yIG1vZGVsaW5nIFZhUiByZWx5IG9uIGEgc2VtaXBhcmFtZXRyaWMgb3IgYSBub25wYXJhbWV0cmljIGhpc3RvcmljYWwgc2ltdWxhdGlvbiAoQUREIENJVEFUSU9OIC0gQk9VRE9VS0gpLiBBY2NvcmRpbmcgdG8gUm9iZXJ0IEVuZ2xlIGFuZCBTaW1vbmUgTWFuZ2FuZWxsaSBpbiBhIDIwMDQgcGFwZXIsIHRoZXNlIG1ldGhvZHMgYXJlIHVzdWFsbHkgY2hvc2VuIGZvciDigJxlbXBpcmljYWwganVzdGlmaWNhdGlvbnMgcmF0aGVyIHRoYW4gb24gc291bmQgc3RhdGlzdGljYWwgdGhlb3J54oCdIChBREQgQ0lUQVRJT04gLSBFTkdMRSkuIEFzIHN1Y2gsIHRoZXkgcHJvcG9zZSBhIGZyYW1ld29yayBjYWxsZWQgQ0FWaWFSIHRoYXQgZm9yZWNhc3RzIHRoZSBWYVIgcXVhbnRpbGUgZGlyZWN0bHkgdXNpbmcgYSBjb25kaXRpb25hbCBhdXRvcmVncmVzc2l2ZSBxdWFudGlsZSBzcGVjaWZpY2F0aW9uLiBUaGlzIGFwcHJvYWNoIGJ1aWxkcyB1cG9uIHRoZSBzdGF0aXN0aWNhbCBsaXRlcmF0dXJlIHRoYXQgZXh0ZW5kcyBsaW5lYXIgcXVhbnRpbGUgbW9kZWxzIHRvIHNldHRpbmdzIGFtZW5hYmxlIHRvIGZpbmFuY2lhbCBtb2RlbGluZywgc3VjaCBhcyB3aXRoIGhldGVyb3NrZWRhc3RpYyBhbmQgbm9uc3RhdGlvbmFyeSBlcnJvciBkaXN0cmlidXRpb25zIChBREQgQ0lUQVRJT04gLSBLT0VOS0VSLCBQT1JUTk9ZKS4KCgojIE1ldGhvZHMgVXNlZAoKQSBjb21tb24gcHJvYmxlbSBpbiBzdGF0aXN0aWNhbCBhbmFseXNpcyBvY2N1cnMgd2hlbiBhIHRyYWluaW5nIHNhbXBsZSBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudCB0aGFuIHRoYXQgb2YgdGhlIHRlc3Qgc2FtcGxlLiBJbml0aWFsIG1vdGl2YXRpb25zIGZvciB0aGlzIHBhcGVyIGludm9sdmVkIGFuYWx5emluZyB0d28gc3RvY2tzIC0gQW1hem9uICh0aWNrZXI6IEFNWk4pIGFuZCBQcm9jdG9yICYgR2FtYmxlICh0aWNrZXI6IFBHKSBhbmQgdGhlaXIgcGVyZm9ybWFuY2UgZHVyaW5nIHRoZSBncmVhdCByZWNlc3Npb24uIEEgcmVsZXZhbnQgcXVlc3Rpb24gb2YgYSBmaW5hbmNpYWwgaW5zdGl0dXRpb24gd291bGQgdW5kZXJzdGFuZGFibHkgYmUgaG93IHRoZWlyIHJpc2sgbW9kZWwgcGVyZm9ybWVkIGR1cmluZyAyMDA4LCBhIGhpZ2hseSB2b2xhdGlsZSBwZXJpb2Qgd2hpY2ggd2FzIGRyaXZlbiBieSB0aGUgIndvcnN0IGZpbmFuY2lhbCBjcmlzaXMgc2luY2UgdGhlIEdyZWF0IERlcHJlc3Npb24iIGFjY29yZGluZyB0byBHYXJ5IEJlY2tlciAoQ0lURSksIGEgTm9iZWwtcHJpemUgd2lubmluZyBFY29ub21pc3QuIEludGVyZXN0aW5nbHksIHRoZSBmb3JlY2FzdCBmb3IgQW1hem9uIHdhcyBmYWlybHkgYWNjdXJhdGUgd2hlcmVhcyB0aGUgZm9yZWNhc3QgZm9yIFBHIHdhcyBub3QuIE9uZSByZWFzb24gZm9yIHRoaXMgY291bGQgYmUgdGhlIGZhY3QgdGhhdCBhIHN0b2NrIGxpa2UgQW1hem9uIHdhcyBoaWdobHkgdm9sYXRpbGUgZHVyaW5nIHRoZSB0cmFpbmluZyBzYW1wbGUsIHdoaWNoIGluY2x1ZGVkIGRhdGEgZnJvbSBwcmV2aW91cyB5ZWFycyAoSE9XIE1BTlk/KSwgYnV0IFBHIHdhcyBmYWlybHkgY2FsbS4gSG93IHdvdWxkIGl0IGJlIHBvc3NpYmxlIGZvciBhIHVuaXZhcmlhdGUgbW9kZWwgc3VjaCBhcyBDQVZpYVIsIHRoYXQgZG9lcyBub3QgZXhwbGljdGx5IGFjY291bnQgZm9yIG90aGVyIGZhY3RvcnMsIHRvIGZvcmVjYXN0IHdlbGw/IFdoYXQgaWYgYSB2b2xhdGlsZSBzdG9jayBzdWNoIGFzIEFNWk4gd2FzIGluY2x1ZGVkIGludG8gdGhlIGZvcmVjYXN0IGZvciBQRyAtIHdvdWxkIGl0IGltcHJvdmUgdGhlIGZvcmVjYXN0PwoKVGh1cywgdGhlIGlkZWEgb2YgY29tYmluaW5nIHN0b2NrcyBpbnRvIGEgbXVsdGl2YXJpYXRlIHNldHRpbmcgdG8gY2FwdHVyZSBjb3JyZWxhdGlvbnMgYW5kIGJldHRlciBmb3JlY2FzdCByaXNrIHdhcyBmb3JtZWQuIEEgbmF0dXJhbCBjaG9pY2UgYXBwZWFyZWQgdG8gYmUgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCwgb3JpZ2luYWxseSBkZXZlbG9wZWQgYnkgU3RvY2sgYW5kIFdhdHNvbiBmb3IgcHJlZGljdGluZyBjb25kaXRpb25hbCBtZWFucyBbVFdPIENJVEFUSU9OU10uIFRoZSBtb2RlbCBmb3IgZm9yZWNhc3RpbmcgdGhlIGNvbmRpdGlvbmFsIG1lYW4gaXMgc3BlY2lmaWVkIGJlbG93LgoKIyMgRGlmZnVzaW9uIEluZGV4IE1vZGVsCgpBIHVzZWZ1bCBtZWFucyBvZiBwcmVkaWN0aW5nIHN0b2NrIG1vdmVtZW50cyBpbiB0aGUgZnV0dXJlIGlzIHRoZSBTdG9jayBhbmQgV2F0c29uIGRpZmZ1c2lvbiBpbmRleC4gVGhlIG1vZGVsIGlzIG91dGxpbmVkIGJlbG93LCB3aGljaCBpcyBhZGFwdGVkIGZyb20gTXVsdGl2YXJpYXRlIFRpbWUgU2VyaWVzIEFuYWx5c2lzIFdpdGggUiBhbmQgRmluYW5jaWFsIEFwcGxpY2F0aW9ucyBieSBSdWV5IFMuIFRzYXkgW0FERCBDSVRBVElPTl0uCgpUaGVyZSBhcmUgdHdvIHJlbGV2YW50IGVxdWF0aW9uczoKCiQkClxib2xkc3ltYm9se3pfdH0gPSBcYm9sZHN5bWJvbHtMZl90fSArIFxib2xkc3ltYm9se1xlcHNpbG9uX3R9CiQkCgphbmQgCgokJAp5X3t0K2h9ID0gXGJvbGRzeW1ib2x7XGJldGFeXHByaW1lIGZfdH0gKyBcYm9sZHN5bWJvbHtlX3t0K2h9fQokJAoKSW4gdGhlIGZpcnN0IGVxdWF0aW9uICRcYm9sZHN5bWJvbHt6X3R9ID0gKHpfezF0fSwgLi4uLiwgel97a3R9KV5ccHJpbWUkIGlzIGFuIG9ic2VydmVkIHRpbWUgc2VyaWVzIHdpdGggbWVhbiAwLCAkXGJvbGRzeW1ib2x7Zl90fSQgaXMgYW4gbS1kaW1lbnNpb25hbCB2ZWN0b3Igb2YgY29tbW9uIGZhY3RvcnMgd2l0aCBtZWFuIDAgYW5kIGlkZW50aXR5IGNvdmFyaWFuY2UgbWF0cml4LCAkXGJvbGRzeW1ib2x7TH0kIGlzIGEgJGskIHggJG0kIGxvYWRpbmcgbWF0cml4LCBhbmQgJFxib2xkc3ltYm9se1xlcHNpbG9uX3R9JCBpcyBhIGkuaS5kLiBzZXF1ZW5jZSBvZiByYW5kb20gdmVjdG9ycyB3aXRoIG1lYW4gMCBhbmQgY292YXJpYW5jZSBtYXRyaXggJFxib2xkc3ltYm9se1xTaWdtYV9lfSQuCgpJbiB0aGUgc2Vjb25kIGVxdWF0aW9uLCB3aGljaCByZXByZXNlbnRzIHRoZSBoLXN0ZXAgYWhlYWQgcHJlZGljdGlvbiBiYXNlZCBvbiAkXGJvbGRzeW1ib2x7Zl90fSQsICR5X3QkIGlzIHRoZSBzY2FsYXIgdGltZSBzZXJpZXMgb2YgaW50ZXJlc3QsICRoJCBpcyB0aGUgZm9yZWNhc3QgaG9yaXpvbiwgJFxib2xkc3ltYm9se1xiZXRhfSQgcmVwcmVzZW50cyB0aGUgdmVjdG9yIG9mIGNvZWZmaWNpZW50cywgYW5kICRlX3QkIGlzIGEgc2VxdWVuY2Ugb2YgdW5jb3JyZWxhdGVkIHJhbmRvbSB2YXJpYWJsZXMgd2l0aCBtZWFuIDAgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiAKClRvIG1vZGVsIHRoZSBkYXRhLCBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzIGlzIHBlcmZvcm1lZCBvbiB0aGUgY292YXJpYXRlcyBkZXNjcmliZWQgYmVsb3cgdG8gb2J0YWluIGFuIGVzdGltYXRlIG9mICRcYm9sZHN5bWJvbHtmX3R9JC4gVGhlbiB0aGUgJFxib2xkc3ltYm9se1xiZXRhfSQgY29lZmZpY2llbnRzIGFyZSBlc3RpbWF0ZWQgdXNpbmcgb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcy4KCiMjIENBVmlhUiBNb2RlbAoKSG93ZXZlciwgd29yayBuZWVkZWQgdG8gYmUgZG9uZSB0byBhbGlnbiB0aGUgZGlmZnVzaW9uIGluZGV4IG1vZGVsIHdpdGggdGhlIENBVmlhUiBtb2RlbCwgd2hpY2ggaXMgZGVmaW5lZCBiZWxvdy4gVGhlIGZvbGxvd2luZyB2YXJpYWJsZXMgYXJlIHJlcXVpcmVkIGZvciB1c2UgaW4gdGhlIENBVmlhUiBtb2RlbDoKCkEgdmVjdG9yIG9mIHBvcnRmb2xpbyByZXR1cm5zIAoKIyMgQWRhcHRpdmUgQ0FWaWFSIE1vZGVsCgokJApmX3QoXGJldGFfMSkgPSBmX3t0LTF9KFxiZXRhXzEpICsgXGJldGFfMVxsZWZ0W1xsZWZ0KDErIFxleHAoR1t5X3t0LTF9IC0gZl97dC0xfShcYmV0YV8xKV0pICBccmlnaHQpXnstMX0gLSBcdGhldGEgXHJpZ2h0XSAKJCQKCiMjIFN5bW1ldHJpYyBBYnNvbHV0ZSBWYWx1ZSBDQVZpYVIgTW9kZWwKCiQkCmZfdChcYm9sZHN5bWJvbHtcYmV0YX0pID0gXGJldGFfMSArIFxiZXRhXzJmX3t0LTF9KFxib2xkc3ltYm9se1xiZXRhfSkgKyBcYmV0YV8zfHlfe3QtMX18CiQkCgojIyBBc3ltbWV0cmljIFNsb3BlIENBVmlhUiBNb2RlbAoKJCQKZl90KFxib2xkc3ltYm9se1xiZXRhfSkgPSBcYmV0YV8xICsgXGJldGFfMmZfe3QtMX0oXGJvbGRzeW1ib2x7XGJldGF9KSArIFxiZXRhXzMoeV97dC0xfSleKyArIFxiZXRhXzQoeV97dC0xfSleLQokJAoKIyMgSW5kaXJlY3QgR0FSQ0ggKDEsMSkgQ0FWaWFSIE1vZGVsCgokJApmX3QoXGJvbGRzeW1ib2x7XGJldGF9KSA9IChcYmV0YV8xICsgXGJldGFfMmZfe3QtMX1eMihcYm9sZHN5bWJvbHtcYmV0YX0pICsgXGJldGFfM3lfe3QtMX1eMileezEvMn0KJCQKCltBREQgU1BFQ0lGSUNBVElPTl0KCkFzIHN1Y2gsIHRoZSBmb2xsb3dpbmcgbW9kZWwgaXMgdXNlZCB0byBjb21iaW5lIHRoZSB0d28gaWRlYXM6CgpWQVIgPSBJTlRFUkNFUFQgKyBQQVNUIFZBTFVFUyArIEFSIENPTVBPTkVOVCArIEVSUk9SCgoKIyBEYXRhIFVzZWQKClRoZSByZXNwb25zZSB2YXJpYWJsZSB1c2VkIGluIHRoaXMgYW5hbHlzaXMgaXMgU1BZLCB3aGljaCBpcyBhbiBleGNoYW5nZS10cmFkZWQgZnVuZCB0aGF0IGFpbXMgdG8gdHJhY2sgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBTJlAgNTAwLCB3aGljaCBpcyBkaXNjdXNzZWQgYWJvdmUuIEl0IGlzIGJyb2FkbHkgdXNlZCBhcyBhIGJlbGx3ZWF0aGVyIG9mIHRoZSBVLlMuIGVjb25vbXkgKENJVEUpLCBhbmQgaGFzIHRoZSBhZHZhbnRhZ2Ugb2YgYXZvaWRpbmcgc3Vydml2b3JzaGlwIGJpYXMgLSB3aGlsZSBhbiBpbmRpdmlkdWFsIHN0b2NrIG1pZ2h0IGdvIGJhbmtydXB0IG9yIG1lcmdlIHdpdGggYW5vdGhlciwgaXQncyByZWFzb25hYmxlIHRvIGFzc3VtZSB0aGF0IHRoZXNlIGlzc3VlcyBkbyBub3QgYXBwbHkgd2l0aCBhbiBFVEYuIAoKRm9sbG93aW5nIHRoaXMgbG9naWMsIHRoZXJlIGFyZSBzZXZlcmFsIGNsYXNzZXMgb2YgcmVzcG9uc2UgdmFyaWFibGVzIHVzZWQgaW4gdGhpcyBhbmFseXNpcy4gVGhlIGZpcnN0IGdyb3VwIGlzIGEgc2V0IG9mIFUuUy4gc2VjdG9yIEVURnMgb2J0YWluZWQgZnJvbSBTZWVraW5nIEFscGhhIHVzaW5nIHRoZSBsaW5rIGJlbG93LiBBcyB3aXRoIHRoZSByZXNwb25zZSB2YXJpYWJsZSwgdGhlc2UgRVRGcyB3ZXJlIHB1YmxpY2x5IHRyYWRlZCB0aHJvdWdob3V0IHRoZSBHcmVhdCBSZWNlc3NzaW9uLgoKaHR0cHM6Ly9zZWVraW5nYWxwaGEuY29tL2V0ZnMtYW5kLWZ1bmRzL2V0Zi10YWJsZXMvc2VjdG9ycwoKYS4gVXRpbGl0aWVzIChYTFUpCmIuIENvbnN1bWVyIFN0YXBsZXMgKFhMUCkKYy4gSGVhbHRoY2FyZSAoWExWKQpkLiBUZWNobm9sb2d5IChYTEspCmUuIENvbnN1bWVyIERpc2NyZXRpb25hcnkgKFhMWSkKZi4gSW5kdXN0cmlhbCAoWExJKQpnLiBGaW5hbmNpYWwgU2VydmljZXMgKFhMRikKaC4gQmFzaWMgTWF0ZXJpYWxzIChYTEIpCmkuIEVuZXJneSAoWExFKQoKVGhlIHNlY29uZCBpcyBHbG9iYWwgU2VjdG9yIEVURnMsIGFsc28gb2J0YWluZWQgZnJvbSBTZWVraW5nIEFscGhhLiBUaGUgcmF0aW9uYWxlIGZvciBpbmNsdWRpbmcgdGhlc2UgaXMgdGhhdCBwZXJoYXBzIHNvbWUgZ2xvYmFsIGV4cG9zdXJlIGlzIHVzZWZ1bCBpbiB1bmRlcnN0YW5kaW5nIHRoZSBicm9hZGVyIG1hcmtldC4KCmEuIFV0aWxpdGllcyAoSlhJKQpiLiBDb25zdW1lciBTdGFwbGVzIChLWEkpCmMuIEhlYWx0aGNhcmUgKElYSikKZC4gVGVsZWNvbW11bmljYXRpb25zIChJWFApCmUuIFRlY2hub2xvZ3kgKElYTikKZi4gQ29uc3VtZXIgRGlzY3JldGlvbmFyeSAoUlhJKQpnLiBJbmR1c3RyaWFsIChFWEkpCmguIEZpbmFuY2lhbCBTZXJ2aWNlcyAoSVhHKQppLiBCYXNpYyBNYXRlcmlhbHMgKE1YSSkKai4gRW5lcmd5IChJWEMpCgpUaGUgdGhpcmQgaXMgYm9uZCBFVEZzLCBhbHNvIG9idGFpbmVkIGZyb20gW0NJVEVdLiBMaWtlIHRoZSBwcmV2aW91cyB0d28sIHRoZXNlIEVURnMgcG90ZW50aWFsbHkgY29udGFpbiBmb3J3YXJkLWxvb2tpbmcgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHN0b2NrIG1hcmtldC4gTGluayBiZWxvdzoKCmEuIGlTaGFyZXMgMS0zIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChTSFkpCmIuIGlTaGFyZXMgNy0xMCBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoSUVGKQpjLiBpU2hhcmVzIDIwKyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoVExUKQpkLiBpU2hhcmVzIGlCb3h4ICQgSW52ZXN0bWVudCBHcmFkZSBDb3Jwb3JhdGUgQm9uZCBFVEYgKExRRCkKCkxhc3RseSwgYWxsIG9mIHRoZSBhYm92ZSBhcmUgcnVuIHRvZ2V0aGVyLgoKIyBSZXN1bHRzCgoKYGBge3J9CiMgUmVhZCBpbiByZWxldmFudCBsaWJyYXJpZXMKbGlicmFyeShtaWNyb2JlbmNobWFyaykKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodHNlcmllcykKbGlicmFyeSh6b28pCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShmb3JtYXR0YWJsZSkKbGlicmFyeShxdWFudHJlZykKbGlicmFyeShNVFMpCmxpYnJhcnkocGxvdDNEKQpsaWJyYXJ5KGNpdHIpCgojIFNldCB1cCB3b3JraW5nIGRpcmVjdG9yeQojIHNldHdkKCJ+L0RvY3VtZW50cy9HaXRIdWIvQ2F2aWFSIikKCiMgc291cmNlKCdjYXZpYXJfU00uUicpCnNvdXJjZSgnfi9Eb2N1bWVudHMvR2l0SHViL0NhdmlhUi9jYXZpYXJfU00uUicpCmBgYAoKYGBge3J9CiMgVGhpcyBjb2RlIGJlbG93IGlzIGZvciB1c2UgaW4gdGhlIENBVmlhUiBzZWN0aW9ucy4KYGBgCgpgYGB7cn0KIyBIZXJlIGlzIGNvZGUgdGhhdCBJJ2xsIHdyYXAgc29tZSBwYXJ0cyBpbiB0byBhdm9pZCBzdXBlcmZsdW91cyBvdXRwdXQKcXVpZXQgPC0gZnVuY3Rpb24oeCkgeyAKICBzaW5rKHRlbXBmaWxlKCkpIAogIG9uLmV4aXQoc2luaygpKSAKICBpbnZpc2libGUoZm9yY2UoeCkpIAp9IApgYGAKCgpgYGB7cn0KIycgVGhpcyBpcyBhIGZ1bmN0aW9uIHdoaWNoIHB1bGxzIGRhdGEgZm9yIHVzZSBpbiB0aGUgQ0FWaWFSIG1vZGVsCiMnCiMnIEBwYXJhbSBzeW1ib2wgLSBzeW1ib2wgdG8gcHVsbAojJyBAcGFyYW0gY29tcGxfY2FzZSAtIGRlZmF1bHRzIHRvIHRydWUuLi5vbmx5IGluY2x1ZGVzIGNvbXBsZXRlIGNhc2VzIGluIHRoZSBkYXRhCiMnIEBwYXJhbSBhZGpfY2xvc2UgLSB1c2UgYWRqdXN0ZWQgY2xvc2luZyBwcmljZXMuIERlZmF1bHQgaXMgeWVzLgojJyBAcGFyYW0gbG9nX3JldHVybiAtIHVzZSBsb2cgcmV0dXJuPyBEZWZhdWx0IGlzIHllcy4KIycKIycgQHJldHVybiAtIGEgZGF0YSBmcmFtZSB3aGljaCBjYW4gYmUgZmVkIGludG8gbGF0ZXIgZnVuY3Rpb25zCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gZGF0YV9wdWxsKCJTUFkiKQpkYXRhX3B1bGwgPSBmdW5jdGlvbihzeW1ib2wsIGNvbXBsX2Nhc2UgPSAxLCBhZGpfY2xvc2UgPSAxLCBsb2dfcmV0dXJuID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpKXsKICAjIFB1bGwgaW4gZGF0YSBmcm9tIHF1YW50bW9kCiAgcmVzcG9uc2VfcHVsbCA9IGdldFN5bWJvbHMoc3ltYm9sLCBhdXRvLmFzc2lnbiA9IEZBTFNFLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkKICAjIEdldCBhZGp1c3RlZCBjbG9zaW5nIHByaWNlCiAgaWYgKGFkal9jbG9zZSA9PSBUUlVFKXsKICAgIGRmID0gQWQocmVzcG9uc2VfcHVsbCkKICB9IGVsc2UgewogICAgZGYgPSBDbChyZXNwb25zZV9wdWxsKQogIH0KICAjIFJldHVybiBjb21wbGV0ZSBjYXNlcyBvbmx5IAogIGlmIChjb21wbF9jYXNlID09IFRSVUUpewogICAgZGYgPSBkZltjb21wbGV0ZS5jYXNlcyhkZiksIF0KICB9IGVsc2V7CiAgICBkZiA9IGRmCiAgfQogICMgQ2FsY3VsYXRlIGxvZyByZXR1cm4gb2YgZGF0YQogIGlmIChsb2dfcmV0dXJuID09IFRSVUUpewogICAgbHIgPSBsb2coZGZbLDFdL3NoaWZ0KGRmWywxXSwgMSwgdHlwZSA9ICJsYWciKSkKICAgICMgQ29tYmluZSBkYXRhCiAgICBkZl9vdXQgPSBjYmluZChkZiwgbHIpCiAgICAjIFJlbmFtZSB0aGUgZGF0YSAKICAgIGNvbG5hbWVzKGRmX291dCkgPC0gYyhzeW09c3ltYm9sLCBwYXN0ZTAoc3ltYm9sLCAiX2xvZ19yZXR1cm4iKSkKICB9IGVsc2V7CiAgICBkZl9vdXQgPSBkZgogIH0KICAjIFJldHVybiBkYXRhCiAgcmV0dXJuKGRmX291dCkKfQoKCmBgYAoKYGBge3J9CiMnIFB1bGwgdGhlIGRhdGEgYW5kIHJ1biB0aGUgQ0FWaWFSIGZ1bmN0aW9uIG9uIGl0CiMnCiMnIEBwYXJhbSBpbnB1dF9kYXRhIC0gZGF0YSB0byB1c2UgaW4gdGhlIGZ1bmN0aW9uCiMnIEBwYXJhbSByYW5nZV9kYXRhIC0gcmFuZ2Ugb2YgdGhlIGRhdGEgdG8gdXNlCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgdmFsdWVzIGZyb20gdGhlIGNhdmlhciBmdW5jdGlvbgojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGNhdmlhcl9wdWxsKHNweSkKY2F2aWFyX3B1bGwgPSBmdW5jdGlvbihpbnB1dF9kYXRhLCByYW5nZV9kYXRhID0gKDI6ZGltKGlucHV0X2RhdGEpWzFdKSl7CiAgIyBSdW4gdGhlIGNhdmlhciBkYXRhCiAgY2F2aWFyIDwtIGNhdmlhck9wdGltKGlucHV0X2RhdGFbcmFuZ2VfZGF0YSwyXSkKICByZXR1cm4oY2F2aWFyKQp9CgpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gZm9yIHByb2R1Y2luZyByb2xsaW5nIHByZWRpY3Rpb25zCiMnIE1vZGVsIDEgPSBTeW1tZXRyaWMgQWJzb2x1dGUgVmFsdWUsIDIgPSBBc3ltbWV0cmljIHNsb3BlLCAzID0gSW5kaXJlY3QgR0FSQ0gsIDQgPSBBZGFwdGl2ZQojJwojJyBAcGFyYW0gaW5wdXRfZGF0YSAtIGlucHV0IGRhdGEgZnJvbSB0aGUgcHJldmlvdXMgZnVuY3Rpb24KIycgQHBhcmFtIHJhbmdlX2RhdGEgLSByYW5nZSBvZiB0aGUgZGF0YSB0byBjb25zaWRlcgojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZm9yZWNhc3RzIHRvIG1ha2UKIycgQHBhcmFtIG1vZGVsIC0gbW9kZWwgdG8gdXNlIChpbnRlZ2VycyAxIHRocm91Z2ggNCkuIERlZmF1bHRzIHRvIDEuIAojJyBAcGFyYW0gbGV2ZWwgLSBsZXZlbCBvZiBzaWduaWZpY2FuY2UgdG8gdXNlLgojJyBAcGFyYW0gRyAtIGFyZ3VtZW50IGZvciB0aGUgayBwYXJhbWV0ZXIgaW4gdGhlIDR0aCBtb2RlbCAoYWRhcHRpdmUpLiBEZWZhdWx0IGlzIDUKIycKIycgQHJldHVybiAtIGFuIHh0cyBvYmplY3Qgd2hpY2ggY29udGFpbnMgcm9sbGluZyBDQVZpYVIgcHJlZGljdGlvbnMKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSByb2xsaW5nX3ByZWRpY3Rpb25zKHNweSwgbmZjc3QgPSAyMikKcm9sbGluZ19wcmVkaWN0aW9ucyA9IGZ1bmN0aW9uKGlucHV0X2RhdGEsIHJhbmdlX2RhdGEgPSAoMjpkaW0oaW5wdXRfZGF0YSlbMV0pLCBuZmNzdCA9IDI1MCwgbW9kZWwgPTEsIGxldmVsID0gMC4wMSwgRyA9IDUsIGNvbCA9IDIpewogICMgUnVuIHRoZSB2YXJwcmVkaWN0IGZ1bmN0aW9uCiAgdmFycHJlZGljdCA8LSByb2xsYXBwbHlyKGlucHV0X2RhdGFbcmFuZ2VfZGF0YSxjb2xdLCBsZW5ndGgocmFuZ2VfZGF0YSkgLSBuZmNzdCwgY2F2aWFyT3B0aW0sIG1vZGVsLCBsZXZlbCwgcHJlZGljdCA9IDEsIGsgPSBHKSAlPiUgbGFnCiAgIyBFbGltaW5hdGUgTkFzCiAgIyBwcmVkX25vX25hID0gbmEub21pdCh2YXJwcmVkaWN0KQogICMgUmV0dXJuIHRoZSBkYXRhCiAgIyByZXR1cm4ocHJlZF9ub19uYSkKICByZXR1cm4odmFycHJlZGljdCkKfQoKYGBgCgpgYGB7cn0KIycgRnVuY3Rpb24gdG8gQ2FsY3VsYXRlIExvc3MgZnJvbSB0aGUgYWJvdmUgcHJlZGljdGlvbnMKIycKIycgQHBhcmFtIHN5bWJvbCAtIHN5bWJvbCB0byB3b3JrIHdpdGggZnJvbSBxdWFudG1vZC4gTXVzdCBiZSBpbiBxdW90YXRpb25zIHRvIHdvcmsKIycgQHBhcmFtIHN0YXJ0X2R0IC0gc3RhcnQgZGF0ZSBvZiB0aGUgZGF0YSB0byBidWlsZCB0aGUgZm9yZWNhc3Qgb24gCiMnIEBwYXJhbSBlbmRfZHQgLSBlbmQgZGF0ZSBvZiB0aGUgZGF0YSB0byBidWlsZCB0aGUgZm9yZWNhc3Qgb24gIAojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdG8gdXNlIGluIHRoZSBmb3JlY2FzdAojJyBAcGFyYW0gbW9kZWwgLSBtb2RlbCB0byB1c2UuIERlZmF1bHRzIHRvIDEKIycgQHBhcmFtIGxldmVsIC0gbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlLiBEZWZhdWx0cyB0byAxJQojJyBAcGFyYW0gRyAtIGFyZ3VtZW50IGZvciB0aGUgayBwYXJhbWV0ZXIgaW4gdGhlIDR0aCBtb2RlbCAoYWRhcHRpdmUpLiBEZWZhdWx0IGlzIDUKIycKIycgQHJldHVybiAtIGxvc3MgdXNpbmcgYWJzb2x1dGUgdmFsdWUKIycgQGV4cG9ydCAtIGEgcGxvdCBvZiB0aGUgZGF0YQojJwojJyBAZXhhbXBsZXMKbG9zc19jYWxjX3V2ID0gZnVuY3Rpb24oc3ltYm9sLCBzdGFydF9kdCwgZW5kX2R0LCBuZmNzdCwgbW9kZWwgPSAxLCBsZXZlbCA9IDAuMDEsIEcgPSA1KXsKICAjIFB1bGwgaW4gdGhlIGRhdGEKICByYXdfZGF0YSA9IGRhdGFfcHVsbChzeW1ib2wsIHN0YXJ0X2RhdGUgPSBzdGFydF9kdCwgZW5kX2RhdGUgPSBlbmRfZHQpCiAgIyBGb3JlY2FzdCBiYXNlZCBvbiB0aGUgZGF0YQogIGZjc3QgPSBuYS5vbWl0KHJvbGxpbmdfcHJlZGljdGlvbnMocmF3X2RhdGEsIG5mY3N0ID0gbmZjc3QsIG1vZGVsID0gbW9kZWwsIGxldmVsID0gbGV2ZWwsIEcgPSBHKSkqKC0xKQogICMgRXh0cmFjdCBhY3R1YWxzCiAgYWN0ID0gdGFpbChyYXdfZGF0YSwgbiA9IG5mY3N0KVssMl0KICAjIEpvaW4gdGhlIHR3byB0b2dldGhlciBhbmQgcmVuYW1lCiAgam9pbiA9IG1lcmdlKGZjc3QsYWN0LGFsbD1UUlVFKQogIGNvbG5hbWVzKGpvaW4pIDwtIGMoIkZjc3RfVmFSIiwgIkFjdF9SZXR1cm4iKQogICMgcHJpbnQoam9pbikKICAjIENhbGN1bGF0ZSB0aGUgbG9zc2VzCiAgbG9zcyA9IGFicyhzdW0oaWZlbHNlKGFjdCA+IGZjc3QsIGxldmVsLCAoLTEpKigxLWxldmVsKSkpKQogICMgUGxvdCB0aGUgZGF0YQogIHBsb3QgPSBwbG90Lnh0cyhqb2luLCBjb2wgPSBjKCJyZWQiLCAiYmxhY2siKSwgbHR5ID0gYygyLDEpLCBtYWluID0gIkxvZyBSZXR1cm4gZnJvbSB0aGUgU1BZIHZzLiBGY3N0LiBWYVIiLGdyaWQuY29sID0gTkEsIGxlZ2VuZC5sb2MgPSAiYm90dG9tbGVmdCIpCiAgcmV0dXJuKGxpc3QobG9zcywgcGxvdCwgYWN0LCBmY3N0KSkKfQoKYGBgCgoKYGBge3IsIGNhY2hlID0gVFJVRX0KIycgVGhpcyBpcyBhIGZ1bmN0aW9uIHdoaWNoIGNyZWF0ZXMgYSBkYXRhIGZyYW1lIGZvciB0aGUgcmVzcG9uc2UgYW5kIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyB0aGF0IHdlJ2xsIGZlZWQgaW50byB0aGUgZGlmZnVzaW9uIGluZGV4CiMnCiMnIEBwYXJhbSBzeW1ib2xfbGlzdCAtIGEgbGlzdCBvZiBzeW1ib2xzIHJlY29nbml6YWJsZSBieSB0aGUgCiMnIEBwYXJhbSByZXNwX3ZhciAtIHRoZSByZXNwb25zZSB2YXJpYWJsZSB3ZSdkIGxpa2UgdG8gZm9yZWNhc3Q7IGRlZmF1bHQgaXMgU1BZCiMnIEBwYXJhbSBjb21wbF9jYXNlIC0gZGVmYXVsdHMgdG8gdHJ1ZS4uLm9ubHkgaW5jbHVkZXMgY29tcGxldGUgY2FzZXMgaW4gdGhlIGRhdGEKIycgQHBhcmFtIGFkal9jbG9zZSAtIHVzZSBhZGp1c3RlZCBjbG9zaW5nIHByaWNlcyBmb3IgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcz8gZGVmYXVsdCBpcyAxIGZvciBZRVMKIycgQHBhcmFtIHJlc3BfYWRqX2Nsb3NlIC0gdXNlIGFkanVzdGVkIGNsb3NpbmcgcHJpY2VzIGZvciB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzPyBkZWZhdWx0IGlzIDEgZm9yIFlFUwojJyBAcGFyYW0gc3RhcnRfZGF0ZSAtIHN0YXJ0aW5nIGRhdGEgdG8gdXNlCiMnIEBwYXJhbSBlbmRfZGF0ZSAtIGVuZGluZyBkYXRlIG9mIHRoZSBkYXRhCiMnIEBwYXJhbSBsYWdfcHJlZCAtIGRvIHdlIGxhZyB0aGUgcHJlZGljdGlvbnM/IEl0IGlzIFNUUk9OR0xZIHJlY29tbWVuZGVkIHRoYXQgdGhpcyBpcyAwCiMnCiMnIEByZXR1cm4gLSBhIGRhdGEgZnJhbWUgd2hpY2ggY2FuIGJlIGZlZCBpbnRvIHRoZSBTV2ZvcmUgZnVuY3Rpb24KIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSBkaWZmX2luZGV4X2RmKGMoIlhMRiIsICJYTEUiLCAiUFNDVCIsICJYTFYiLCAiVlBVIiwgIlhMUCIsICJJR0YiLCAiWFdFQiIsICJQUFRZIikpCmRpZmZfaW5kZXhfZGYgPSBmdW5jdGlvbihzeW1ib2xfbGlzdCwgcmVzcF92YXIgPSAiU1BZIiwgY29tcGxfY2FzZSA9IDEsIGFkal9jbG9zZSA9IDEsIHJlc3BfYWRqX2Nsb3NlID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpLCBsYWdfcHJlZCA9IDEpewogICMgUHVsbCBpbiByZXNwb25zZSB2YXJpYWJsZQogIHJlc3BvbnNlX3B1bGwgPSBnZXRTeW1ib2xzKHJlc3BfdmFyLCBhdXRvLmFzc2lnbiA9IEZBTFNFLCBmcm9tID0gc3RhcnRfZGF0ZSwgdG8gPSBlbmRfZGF0ZSkKICAjIEdldCBhZGp1c3RlZCBjbG9zaW5nIHByaWNlCiAgaWYgKHJlc3BfYWRqX2Nsb3NlID09IFRSVUUpewogICAgZGlmZl9kZiA9IEFkKHJlc3BvbnNlX3B1bGwpCiAgfSBlbHNlIHsKICAgIGRpZmZfZGYgPSBDbChyZXNwb25zZV9wdWxsKQogIH0KICAjIExvb3AgdGhyb3VnaCB0aGUgc3ltYm9scyBhbmQgam9pbiBpbiBkYXRhCiAgZm9yIChpIGluIDE6bGVuZ3RoKHN5bWJvbF9saXN0KSl7CiAgICAjIFB1bGwgY2xvc2luZyBwcmljZQogICAgZXhwbF9wdWxsID0gZ2V0U3ltYm9scyhzeW1ib2xfbGlzdFtpXSwgYXV0by5hc3NpZ24gPSBGQUxTRSwgZnJvbSA9IHN0YXJ0X2RhdGUsIHRvID0gZW5kX2RhdGUpCiAgICAjIEV4dHJhY3QgY2xvc2luZyBwcmljZSAtIDR0aCBlbGVtZW50CiAgICBpZiAoYWRqX2Nsb3NlID09IFRSVUUpewogICAgICBleHBsX2NsID0gQWQoZXhwbF9wdWxsKQogICAgfSBlbHNlIHsKICAgICAgZXhwbF9jbCA9IENsKGV4cGxfcHVsbCkKICAgIH0KICAgICMgTmV3IGNvZGUgZm9yIDQuMTYuMjAyMCAtIGxhZyB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGVzCiAgICBpZiAobGFnX3ByZWQgPT0gVFJVRSl7CiAgICAgICMgTGFnIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYnkgMQogICAgICBsYWdfZXhwID0gbGFnKGV4cGxfY2wsIDEpCiAgICAgICMgQXBwZW5kIHRoZSBmaXJzdCBsYWcgdG8gdGhlIGRhdGEgZnJhbWUKICAgICAgZGlmZl9kZiA9IG1lcmdlKGRpZmZfZGYsIGxhZ19leHAsIGpvaW4gPSAibGVmdCIsIGZpbGwgPSBOQSkKICAgIH0gZWxzZXsKICAgICAgIyBSZXR1cm4gdGhlIGRhdGEgZnJhbWUgd2l0aG91dCBsYWdzCiAgICAgIGRpZmZfZGYgPSBtZXJnZShkaWZmX2RmLCBleHBsX2NsLCBqb2luID0gImxlZnQiLCBmaWxsID0gTkEpCiAgICB9CiAgfQogIGlmIChsYWdfcHJlZCA9PSBUUlVFKXsKICAgICMgQ2hvcCBvZmYgdGhlIGZpcnN0IHJvdwogICAgZGlmZl9kZiA9IGRpZmZfZGZbLTEsXQogIH0KICBlbHNlIHsKICAgIHByaW50KCJQTEVBU0UgTk9URSAtIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgaW4gdGhpcyBERiBhcmUgTk9UIGxhZ2dlZC4gQmUgY2FyZWZ1bCB0byBhdm9pZCBsb29rLWFoZWFkIGJpYXMhIikKICB9CiAgIyBSZXR1cm4gY29tcGxldGUgY2FzZXMgb25seSAKICBpZiAoY29tcGxfY2FzZSA9PSBUUlVFKXsKICAgIGRpZmZfZGZfb3V0ID0gZGlmZl9kZltjb21wbGV0ZS5jYXNlcyhkaWZmX2RmKSwgXQogIH0gZWxzZXsKICAgIGRpZmZfZGZfb3V0ID0gZGlmZl9kZgogIH0KICAKICByZXR1cm4oZGlmZl9kZl9vdXQpCn0KCmBgYAoKYGBge3IsIGNhY2hlID0gVFJVRX0KIycgQ29udmVydHMgYSBkaWZmX2RmIGludG8gYSBkYXRhIGZyYW1lIHdpdGggYXBwcm94aW1hdGUgcGVyY2VudGFnZSBjaGFuZ2VzIGRpZmYobG9nKGRpZmZfZGYpKQojJwojJyBAcGFyYW0gZGlmZl9kZiAtIG91dHB1dCBvZiB0aGUgZGlmZl9pbmRleF9kZiBmdW5jdGlvbiB3aXRoIGNvbXBsZXRlIGNhc2VzCiMnCiMnIEByZXR1cm4gLSByZXR1bnMgdGhlIGRpZmZlcmVuY2VkIGRhdGEKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMgLSBwY19kaWZmX2luZGV4KHRlc3RfY29tcGwpIAoKcGNfZGlmZl9pbmRleCA9IGZ1bmN0aW9uKGRpZmZfZGYpewogICMgRGlmZmVyZW5jZSB0aGUgbG9nIG9mIHRoZSBkYXRhCiAgcGNfZGlmZl9pbmRleCA9IGRpZmYobG9nKGRpZmZfZGYpKQogICMgUmVtb3ZlIHRoZSBmaXJzdCByb3cKICBwY19kaWZmX2luZGV4X291dCA9IHBjX2RpZmZfaW5kZXhbLTEsXQogIHJldHVybihwY19kaWZmX2luZGV4X291dCkKfQoKYGBgCgoKYGBge3J9CiMnIEJlbG93IGlzIHRoZSBtb2RpZmllZCBkaWZmdXNpb24gaW5kZXggY29kZS4KIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZQojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGV4ZXMgdXNlZAojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZTsgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEKIycgQHBhcmFtIGVuZCAtIHNwZWNpZmllcyBhbiBhbHRlcm5hdGUgZW5kaW5nIHZhbHVlCiMnIEBwYXJhbSBwcmludF9tZGwgLSBwcmludCB0aGUgbW9kZWwgc3VtbWFyeSBhbmQgdGhlIE1TRQojJwojJyBAcmV0dXJuIC0gcmV0dXJucyBhIGxpc3Qgb2YgdmFyaWFibGVzIGZvciB1c2UgaW4gdGhlIGRpZmZ1c2lvbiBpbmRleAojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcwptb2RfZGkgPSBmdW5jdGlvbiAoeSwgeCwgb3JpZywgbSwgdGF1LCBlbmQgPSBOVUxMLCBwcmludF9tZGwgPSAwKSAKewogICMgQ29udmVydHMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlcyBpbnRvIGEgbWF0cml4CiAgaWYgKCFpcy5tYXRyaXgoeCkpIAogICAgICB4ID0gYXMubWF0cml4KHgpCiAgIyBuVCBpcyBudW1iZXIgb2YgdCB0aW1lLXN0ZXBzCiAgblQgPSBkaW0oeClbMV0KICAjIEFkZCBhIGxpbmUgdG8gZXN0YWJsaXNoIHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdXNlZCBpbiB0aGUgdGVzdC4KICBpZiAoaXMubnVsbChlbmQpICE9IFRSVUUpewogICAgblQgPSBlbmQKICB9CiAgIyBrIGlzIHRoZSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdXNlZAogIGsgPSBkaW0oeClbMl0KICAjIFNhbml0eSBjaGVja3MgdG8gZW5zdXJlIHRoYXQgdGhlIG9yaWdpbiBpc24ndCBwYXN0IHRoZSBudW1iZXIgb2YgdGltZSBwb2ludHMKICBpZiAob3JpZyA+IG5UKSAKICAgICAgb3JpZyA9IG5UCiAgIyBNYWtlcyBzdXJlIHRoYXQgdGhlcmUgYXJlbid0IG1vcmUgcHJlZGljdG9ycyB0aGFuIHRoZXJlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldAogIGlmIChtID4gaykgCiAgICAgIG0gPSBrCiAgIyBNYWtlcyBzdXJlIHRoZXJlIGFyZSBhdCBsZWFzdCBzb21lIHZhcmlhYmxlcwogIGlmIChtIDwgMSkgCiAgICAgIG0gPSAxCiAgIyBTdWJkaXZpZGVzIHRoZSBkYXRhZnJhbWUKICB4MSA9IHhbMTpvcmlnLCBdCiAgIyBDYWxjdWxhdGVzIG1lYW5zIG9mIGVhY2ggcm93CiAgbWUgPSBhcHBseSh4MSwgMiwgbWVhbikKICAjIENhbGN1bGF0ZXMgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlYWNoIGNvbHVtbgogIHNlID0gc3FydChhcHBseSh4MSwgMiwgdmFyKSkKICAjIENyZWF0ZXMgYSBtYXRyaXggeDEsIHdoaWNoIG5vcm1hbGl6ZXMgYWxsIHRoZSBjb2x1bW5zLiAKICAjIFRoaXMgbWF5IGJlIGFuIGlzc3VlIHNpbmNlIGl0IGFzc3VtZXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIGlzIHN1ZmZpY2llbnRseSBkZXNjcmliZWQgYnkgdGhlIGZpcnN0IHR3byBtb21lbnRzCiAgeDEgPSB4CiAgZm9yIChpIGluIDE6aykgewogICAgICB4MVssIGldID0gKHgxWywgaV0gLSBtZVtpXSkvc2VbaV0KICB9CiAgVjEgPSBjb3YoeDFbMTpvcmlnLCBdKQogICMgUGVyZm9ybXMgYW4gZWlnZW4gZGVjb21wb3NpdGlvbgogIG0xID0gZWlnZW4oVjEpCiAgIyBTZWxlY3RzIGVpZ2VudmFsdWVzCiAgc2RldiA9IG0xJHZhbHVlcwogICMgU2VsZWN0cyBlaWdlbnZlY3RvcnMKICBNID0gbTEkdmVjdG9ycwogICMgTWFrZXMgYSBzbWFsbGVyIG1hdHJpeAogIE0xID0gTVssIDE6bV0KICAjIFRoaXMgaXMgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCAtIFtvcmlnIHggcF0qW3AgeCBtXSA9IFtvcmlnIHggbV0KICBEaW5kZXggPSB4MSAlKiUgTTEKICAjIEN1dCBkb3duIGJvdGggdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3JzIHRvIGJlIGEgcmVhc29uYWJsZSBzaXplCiAgeTEgPSB5WzE6b3JpZ10KICBERiA9IERpbmRleFsxOm9yaWcsIF0KICAjIEFwcGx5IHRoZSBsaW5lYXIgbW9kZWwgLSBIRVJFIGlzIHRoZSBrZXkuCiAgIyBtbSA9IGxtKHkxIH4gREYpIC0gb2xkIGZ1bmN0aW9uCiAgbW0gPSBycSh5MSB+IERGLCB0YXUgPSB0YXUpCiAgIyBQcmludCB0aGUgZGF0YQogIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICBwcmludChzdW1tYXJ5KG1tKSkKICB9CiAgIyBQdXRzIGNvZWZmaWNpZW50cyBpbiBhIG1hdHJpeAogIGNvZWYgPSBtYXRyaXgobW0kY29lZmZpY2llbnRzLCAobSArIDEpLCAxKQogICMgSW5pdGlhbGl6ZXMgeWhhdCB2YXJpYWJsZXMgYW5kIE1TRQogIHloYXQgPSBOVUxMCiAgTVNFID0gTlVMTAogIGlmIChvcmlnIDwgblQpIHsKICAgICMgQ3JlYXRlcyBhIG5mY3N0IGJ5IChtKzEpIG1hdHJpeAogICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCAKICAgICAgICBdKQogICAgIyBbbmZjc3R4KG0rMSldKlsobSsxKXgxXSA9IFtuZmNzdHgxXQogICAgeWhhdCA9IG5ld3ggJSolIGNvZWYKICAgICMgQ2FsY3VsYXRlcyBlcnJvcnMKICAgIGVyciA9IHlbKG9yaWcgKyAxKTpuVF0gLSB5aGF0CiAgICBNU0UgPSBtZWFuKGVycl4yKQogICAgaWYgKHByaW50X21kbCA9PSAxKXsKICAgICAgY2F0KCJNU0Ugb2Ygb3V0LW9mLXNhbXBsZSBmb3JlY2FzdHM6ICIsIE1TRSwgIlxuIikKICAgIH0KICB9CiAgU1dmb3JlIDwtIGxpc3QoY29lZiA9IGNvZWYsIHloYXQgPSB5aGF0LCBNU0UgPSBNU0UsIGxvYWRpbmdzID0gTTEsIAogICAgICBERmluZGV4ID0gRGluZGV4KQp9CgpgYGAKCgpgYGB7cn0KIycgQmVsb3cgaXMgdGhlIG1vZGlmaWVkIGRpZmZ1c2lvbiBpbmRleCBjb2RlIHRvIGluY2x1ZGUgbGFnZ2VkIHZhcmlhYmxlcy4KIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZQojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGV4ZXMgdXNlZAojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZTsgbXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEKIycgQHBhcmFtIGFyX3RmIC0gQVIgdHJhbnNmb3JtYXRpb24gdHlwZS4gKDEgLSBubyB0cmFuc2Zvcm1hdGlvbiwKIycgMiAtIGFic29sdXRlIHZhbHVlLCAzIC0gYXN5bW1ldHJpYyBzbG9wZSkKIycgQHBhcmFtIHAgLSBudW1iZXIgb2YgQVIgbGFncyB0byBpbmNsdWRlLiBEZWZhdWx0IGlzIG9uZS4KIycgQHBhcmFtIHByaW50X21kbCAtIG9wdGlvbiB0byBwcmludCB0aGUgbW9kZWwgc3VtbWFyeSB0byBtYWtlIHN1cmUgZXZlcnl0bmluZyBpcyBvay4gMCBpcyBkZWZhdWx0LgojJyBAcGFyYW0gbW9kZWwgLSBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKIycKIycgQHJldHVybiAtIHJldHVybnMgYSBsaXN0IG9mIHZhcmlhYmxlcyBmb3IgdXNlIGluIHRoZSBkaWZmdXNpb24gaW5kZXgKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKbW9kX2RpX3dsID0gZnVuY3Rpb24gKHksIHgsIG9yaWcsIG0sIHRhdSwgYXJfdGYgPSAxLCBwID0gMSwgcHJpbnRfbWRsID0gMCwgbW9kZWwgPSAxLCBlbmQgPSBOVUxMKSAKewogICMgQ29udmVydHMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlcyBpbnRvIGEgbWF0cml4CiAgaWYgKCFpcy5tYXRyaXgoeCkpIAogICAgICB4ID0gYXMubWF0cml4KHgpCiAgIyBuVCBpcyBudW1iZXIgb2YgdCB0aW1lLXN0ZXBzCiAgblQgPSBkaW0oeClbMV0KICAjIEFkZCBhIGxpbmUgdG8gZXN0YWJsaXNoIHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgdXNlZCBpbiB0aGUgdGVzdC4KICBpZiAoaXMubnVsbChlbmQpICE9IFRSVUUpewogICAgblQgPSBlbmQKICB9CiAgIyBrIGlzIHRoZSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdXNlZAogIGsgPSBkaW0oeClbMl0KICAjIFNhbml0eSBjaGVja3MgdG8gZW5zdXJlIHRoYXQgdGhlIG9yaWdpbiBpc24ndCBwYXN0IHRoZSBudW1iZXIgb2YgdGltZSBwb2ludHMKICBpZiAob3JpZyA+IG5UKSAKICAgICAgb3JpZyA9IG5UCiAgIyBNYWtlcyBzdXJlIHRoYXQgdGhlcmUgYXJlbid0IG1vcmUgcHJlZGljdG9ycyB0aGFuIHRoZXJlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldAogIGlmIChtID4gaykgCiAgICAgIG0gPSBrCiAgIyBNYWtlcyBzdXJlIHRoZXJlIGFyZSBhdCBsZWFzdCBzb21lIHZhcmlhYmxlcwogIGlmIChtIDwgMSkgCiAgICAgIG0gPSAxCiAgIyBTdWJkaXZpZGVzIHRoZSBkYXRhZnJhbWUKICB4MSA9IHhbMTpvcmlnLCBdCiAgIyBDYWxjdWxhdGVzIG1lYW5zIG9mIGVhY2ggcm93CiAgbWUgPSBhcHBseSh4MSwgMiwgbWVhbikKICAjIENhbGN1bGF0ZXMgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlYWNoIGNvbHVtbgogIHNlID0gc3FydChhcHBseSh4MSwgMiwgdmFyKSkKICAjIENyZWF0ZXMgYSBtYXRyaXggeDEsIHdoaWNoIG5vcm1hbGl6ZXMgYWxsIHRoZSBjb2x1bW5zLiAKICAjIFRoaXMgbWF5IGJlIGFuIGlzc3VlIHNpbmNlIGl0IGFzc3VtZXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIGlzIHN1ZmZpY2llbnRseSBkZXNjcmliZWQgYnkgdGhlIGZpcnN0IHR3byBtb21lbnRzCiAgeDEgPSB4CiAgZm9yIChpIGluIDE6aykgewogICAgICB4MVssIGldID0gKHgxWywgaV0gLSBtZVtpXSkvc2VbaV0KICB9CiAgVjEgPSBjb3YoeDFbMTpvcmlnLCBdKQogICMgUGVyZm9ybXMgYW4gZWlnZW4gZGVjb21wb3NpdGlvbgogIG0xID0gZWlnZW4oVjEpCiAgIyBTZWxlY3RzIGVpZ2VudmFsdWVzCiAgc2RldiA9IG0xJHZhbHVlcwogICMgU2VsZWN0cyBlaWdlbnZlY3RvcnMKICBNID0gbTEkdmVjdG9ycwogICMgTWFrZXMgYSBzbWFsbGVyIG1hdHJpeAogIE0xID0gTVssIDE6bV0KICAjIFRoaXMgaXMgdGhlIGRpZmZ1c2lvbiBpbmRleCBtb2RlbCAtIFtvcmlnIHggcF0qW3AgeCBtXSA9IFtvcmlnIHggbV0KICBEaW5kZXggPSB4MSAlKiUgTTEKICAjIEN1dCBkb3duIGJvdGggdGhlIHJlc3BvbnNlIGFuZCBwcmVkaWN0b3JzIHRvIGJlIGEgcmVhc29uYWJsZSBzaXplCiAgeTEgPSB5WzE6b3JpZ10KICBERiA9IERpbmRleFsxOm9yaWcsIF0KICAjIENvcHkgdGhlIGRhdGEgZnJhbWUKICBERl93bCA9IERpbmRleAogICMgTGFnIHRoZSB5LXZhcmlhYmxlCiAgZm9yIChpIGluIDE6cCl7CiAgICAjIENyZWF0ZSBhIGxhZ2dlZCB2YXJpYWJsZQogICAgbGFnX3ZhciA9IGxhZyh5LCBpKQogICAgIyBBcHBlbmQgdGhlIGZpcnN0IGxhZyB0byB0aGUgZGF0YSBmcmFtZQogICAgREZfd2wgPSBjYmluZChERl93bCxsYWdfdmFyKQogIH0KICAjIElkZW50aWZ5IHRoZSByaWdodCBjb2x1bW5zCiAgbF9hciA9IG5jb2woREZfd2wpCiAgZl9hciA9IGxfYXIgLSBwICsgMQogICMgS2VlcCB0aGUgbGFzdCBjb2x1bW5zIGtlcHQgdG8gdGhlIHNpZGUKICBhbGxfbGFnID0gREZfd2xbLChmX2FyOmxfYXIpXQogICMgQ3V0IG9mZiB0aGUgZmlyc3Qgcm93IHRvIGF2b2lkIE5BJ3MKICBERl90cmltID0gREZfd2xbMTpvcmlnLF0KICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICMgSGVyZSdzIHRoZSBuZXcgZnVuY3Rpb24gd2l0aCBhbiB1bnRyYW5zZm9ybWVkIEFSKHApIGxhZwogIGlmIChhcl90ZiA9PSAxKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLF0pCiAgICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICAgIyBJbml0aWFsaXplIGEgY2hhcmFjdGVyIHZlY3RvcgogICAgbnZlYyA9IGMocmVwKDAsIDErbStwKSkKICAgICMgUG9wdWxhdGUgdGhlIHZlY3RvciAtIGZpcnN0IHZhbHVlIGlzIHRoZSByZXNwb25zZQogICAgbnZlY1sxXSA8LSBuYW1lcyh5KQogICAgIyBOZXh0IGFyZSB0aGUgZGlmZnVzaW9uIGluZGljZXMKICAgIGZvciAoaSBpbiAxOm0pewogICAgICBudmVjW2krMV0gPSBwYXN0ZTAoIkRpZmZfSW5kZXhfIiwgaSkKICAgIH0KICAgICMgTmV4dCBhcmUgdGhlIGxhZ2dlZCB2YXJpYWJsZXMKICAgIGZvciAoaSBpbiAxOnApewogICAgICBudmVjW2krMSttXSA9IHBhc3RlMCgiTGFnXyIsIGkpCiAgICB9CiAgICAjIEFzc2lnbiB0aGUgbmFtZXMKICAgIG5hbWVzKGRmX2luKSA8LSBudmVjCiAgICAjIFJ1biB0aGUgbW9kZWwKICAgIG1tID0gcnEoZGZfaW5bLDFdIH4gZGZfaW5bLC0xXSwgdGF1ID0gdGF1KQogIH0KICAjIEhlcmUncyB0aGUgbmV3IGZ1bmN0aW9uIHdpdGggYW4gU0FWIEFSKHApIGxhZwogIGlmIChhcl90ZiA9PSAyKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLC0oZl9hcjpsX2FyKV0sIGFicyhERl90cmltWy0oMTpwKSwoZl9hcjpsX2FyKV0pKQogICAgIyBSZW5hbWUgdGhlIGNvbHVtbnMKICAgICMgSW5pdGlhbGl6ZSBhIGNoYXJhY3RlciB2ZWN0b3IKICAgIG52ZWMgPSBjKHJlcCgwLCAxK20rcCkpCiAgICAjIFBvcHVsYXRlIHRoZSB2ZWN0b3IgLSBmaXJzdCB2YWx1ZSBpcyB0aGUgcmVzcG9uc2UKICAgIG52ZWNbMV0gPC0gbmFtZXMoeSkKICAgICMgTmV4dCBhcmUgdGhlIGRpZmZ1c2lvbiBpbmRpY2VzCiAgICBmb3IgKGkgaW4gMTptKXsKICAgICAgbnZlY1tpKzFdID0gcGFzdGUwKCJEaWZmX0luZGV4XyIsIGkpCiAgICB9CiAgICAjIE5leHQgYXJlIHRoZSBsYWdnZWQgdmFyaWFibGVzCiAgICBmb3IgKGkgaW4gMTpwKXsKICAgICAgbnZlY1tpKzErbV0gPSBwYXN0ZTAoIkxhZ18iLCBpKQogICAgfQogICAgIyBBc3NpZ24gdGhlIG5hbWVzLiBOb3RlIHRoYXQgdGhpcyBpcyBhIG1hdHJpeAogICAgbmFtZXMoZGZfaW4pIDwtIG52ZWMKICAgICMgUnVuIHRoZSBtb2RlbAogICAgbW0gPSBycShkZl9pblssMV0gfiBkZl9pblssLTFdLCB0YXUgPSB0YXUpCiAgfQogICMgSGVyZSdzIHRoZSBuZXcgZnVuY3Rpb24gd2l0aCBhbiBhc3ltbWV0cmljIHNsb3BlIGZvciB0aGUgQVIoMSkgbGFnCiAgIyBJbmRpY2F0b3I7IDAgaWYgcGVyY2VudCBjaGFuZ2UgaXMgbmVnYXRpdmUsIDEgaWYgaXQncyBwb3NpdGl2ZQogICMgaW5kaSA9IGlmZWxzZShERl90cmltWyxhcl0gPCAwLCAwLCAxKQogIGlmIChhcl90ZiA9PSAzKXsKICAgICMgQ3JlYXRlIGEgbWF0cml4IG9mIGluZGljYXRvcnMKICAgIGluZGlfbWF0ID0gbWF0cml4KDAsIG5yb3coREZfd2wpLCBwKQogICAgIyBHZW5lcmFsaXplIHRoZSBhYm92ZSBjb2RlCiAgICBmb3IgKGkgaW4gMTpwKXsKICAgICAgIyBQb3B1bGF0ZSB0aGUgaW5kaWNhdG9yCiAgICAgIGluZGlfbWF0WyxpXSA9IGlmZWxzZShERl93bFssZl9hciArIGkgLSAxXSA8IDAsIDAsIDEpCiAgICB9CiAgfQogICMgRml0dGluZyB0aGUgcmVncmVzc2lvbgogIGlmIChhcl90ZiA9PSAzKXsKICAgICMgSW5jb3Jwb3JhdGUgZXZlcnl0aGluZyBpbiB0byBhbiBpbnB1dCBkYXRhIGZyYW1lCiAgICBkZl9pbiA9IGNiaW5kKHkxWy0oMTpwKV0sIERGX3RyaW1bLSgxOnApLC0oZl9hcjpsX2FyKV0sIERGX3RyaW1bLSgxOnApLChmX2FyOmxfYXIpXSwgaW5kaV9tYXRbKChwKzEpOm9yaWcpLF0pCiAgICAjIFJlbmFtZSB0aGUgY29sdW1ucwogICAgIyBJbml0aWFsaXplIGEgY2hhcmFjdGVyIHZlY3RvcgogICAgbnZlYyA9IGMocmVwKDAsIDErbSsyKnApKQogICAgIyBQb3B1bGF0ZSB0aGUgdmVjdG9yIC0gZmlyc3QgdmFsdWUgaXMgdGhlIHJlc3BvbnNlCiAgICBudmVjWzFdIDwtIG5hbWVzKHkpCiAgICAjIE5leHQgYXJlIHRoZSBkaWZmdXNpb24gaW5kaWNlcwogICAgZm9yIChpIGluIDE6bSl7CiAgICAgIG52ZWNbaSsxXSA9IHBhc3RlMCgiRGlmZl9JbmRleF8iLCBpKQogICAgfQogICAgIyBOZXh0IGFyZSB0aGUgbGFnZ2VkIHZhcmlhYmxlcwogICAgZm9yIChpIGluIDE6cCl7CiAgICAgIG52ZWNbaSsxK21dID0gcGFzdGUwKCJMYWdfIiwgaSkKICAgIH0KICAgICMgTGFzdCBhcmUgdGhlIHBvc2l0aXZlIGluZGljYXRvciB2YXJpYWJsZXMKICAgIGZvciAoaSBpbiAxOnApewogICAgICBudmVjW2krMSttK3BdID0gcGFzdGUwKCJQb3NfVmFsX2Zvcl9MYWdfIiwgaSkKICAgIH0KICAgICMgQXNzaWduIHRoZSBuYW1lcy4gTm90ZSB0aGF0IHRoaXMgaXMgYSBtYXRyaXgKICAgIG5hbWVzKGRmX2luKSA8LSBudmVjCiAgICAjIFJ1biB0aGUgbW9kZWwKICAgIG1tID0gcnEoZGZfaW5bLDFdIH4gZGZfaW5bLC0xXSwgdGF1ID0gdGF1KQogICAgIyBtbSA9IHJxKHkxWy0oMTpwKV0gfiBERl90cmltWy0oMTpwKSwtKGZfYXI6bF9hcildICsgREZfdHJpbVstKDE6cCksKGZfYXI6bF9hcildICsgaW5kaV9tYXRbKChwKzEpOm9yaWcpLF0sIHRhdSA9IHRhdSkKICAgICMgQWRkIGEgZGlmZmVyZW50IGxpbmUgdG8gYWNjb3VudCBmb3IgdGhlIGluZGljYXRvciB2YXJpYWJsZQogICAgIyBpbnRlcmNlcHQgKyBtICsgMipubGFnIHRvIGFjY291bnQgZm9yIHRoZSBudW1iZXIgb2YgaW5kaWNhdG9yIHZhcmlhYmxlcwogICAgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsICgxICsgbSArIDIqcCksIDEpCiAgfQogIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICBwcmludChzdW1tYXJ5KG1tKSkKICB9CiAgIyBQdXRzIGNvZWZmaWNpZW50cyBpbiBhIG1hdHJpeCAtIGFkZGVkIHRoZSBBUiB0ZXJtcwogICMgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsIChtICsgMSksIDEpCiAgaWYgKGFyX3RmICE9IDMpewogICAgY29lZiA9IG1hdHJpeChtbSRjb2VmZmljaWVudHMsICgxICsgbSArIHApLCAxKQogIH0KICAjIEluaXRpYWxpemVzIHloYXQgdmFyaWFibGVzIGFuZCBNU0UKICB5aGF0ID0gTlVMTAogIGxvc3MgPSBOVUxMCiAgaWYgKG9yaWcgPCBuVCkgewogICAgIyBDcmVhdGVzIGEgbmZjc3QgYnkgKG0rMikgbWF0cml4CiAgICAjIEFkZCBvbiB0aGUgbGFnZ2VkIHZhcmlhYmxlcwogICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCBdLCBhbGxfbGFnWyhvcmlnKzEpOm5ULF0pCiAgICAjIEluY29ycG9yYXRlIGxhZ2dlZCB2YXJpYWJsZXMKICAgIGlmIChhcl90ZiA9PSAzKXsKICAgICAgbmV3eCA9IGNiaW5kKHJlcCgxLCAoblQgLSBvcmlnKSksIERpbmRleFsob3JpZyArIDEpOm5ULCBdLCBhbGxfbGFnWyhvcmlnKzEpOm5ULF0sIGluZGlfbWF0WyhvcmlnKzEpOm5ULF0pCiAgICB9CiAgICAjIFtuZmNzdHgobSsxKV0qWyhtKzEpeDFdID0gW25mY3N0eDFdCiAgICB5aGF0ID0gbmV3eCAlKiUgY29lZgogICAgIyBDYWxjdWxhdGVzIGVycm9ycwogICAgbG9zcyA9IGFicyhzdW0oaWZlbHNlKHlbKG9yaWcgKyAxKTpuVF0gPiB5aGF0LCB0YXUsICgtMSkqKDEtdGF1KSkpKQogICAgIyBNb2RpZnlpbmcgdGhpcyBwYXJ0IHRvIG9ubHkgcHJpbnQgdGhpcyBpZiBzcGVjaWZpZWQKICAgIGlmIChwcmludF9tZGwgPT0gMSl7CiAgICAgIGNhdCgiTG9zc2VzIG9mIG91dC1vZi1zYW1wbGUgZm9yZWNhc3RzOiAiLCBsb3NzLCAiXG4iKQogICAgfQogIH0KICBTV2ZvcmUgPC0gbGlzdChjb2VmID0gY29lZiwgeWhhdCA9IHloYXQsIGxvc3MgPSBsb3NzLCBsb2FkaW5ncyA9IE0xLCAKICAgICAgREZpbmRleCA9IERpbmRleCwgbmFtZV92ZWN0b3IgPSBudmVjKQp9CgpgYGAKCmBgYHtyfQojIERlY2lkZSBvbiB0aGUgb3B0aW1hbCBudW1iZXIgb2YgdmVjdG9ycy4KCiMgKHksIHgsIG9yaWcsIG0sIHRhdSkgCgojJyBGdW5jdGlvbiB0aGF0IGNhbGN1bGF0ZXMgbG9zcyBvdmVyIGEgZ2l2ZW4gcGVyaW9kIG9mIHRpbWUgZm9yIHRoZSBkaWZmdXNpb24gaW5kZXggbW9kZWwKIycKIycgQHBhcmFtIHkgLSByZXNwb25zZSB2YXJpYWJsZXMKIycgQHBhcmFtIHggLSBleHBsYW5hdG9yeSB2YXJpYWJsZQojJyBAcGFyYW0gb3JpZyAtIGZvcmVjYXN0IG9yaWdpbgojJyBAcGFyYW0gZW5kIC0gZm9yZWNhc3RpbmcgZW5kaW5nLiBOb3RlOiBhcyB0aGUgZnVuY3Rpb24gaXMgY3VycmVudGx5IHdyaXR0ZW4gb24gMi8yNCwgdGhpcyBvcHRpb24gZG9lc24ndCBkbyBhbnl0aGluZy4KIycgQHBhcmFtIG0gLSBudW1iZXIgb2YgZGlmZnVzaW9uIGluZGljZXMgdG8gdXNlCiMnIEBwYXJhbSB0YXUgLSBWYVIgbGV2ZWwKIycgQHBhcmFtIG1vZF9kaSAtIHVzZSB0aGUgbW9kaWZpZWQgREk/CiMnCiMnIEByZXR1cm4gLSByZXR1cm5zIGEgbGlzdCBvZiB0aGUgbG9zcyBzdW0gYW5kIHRoZSBsb3NzIHZlY3RvcgojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGxvc3NfY2FsYyhwY19kZlssMV0sIHBjX2RmWywtMV0sIDc1NywgMTAyNywgMSwgMC4wMSkKbG9zc19jYWxjID0gZnVuY3Rpb24oeSwgeCwgb3JpZywgbSwgdGF1LCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEsIGVuZCA9IE5VTEwpewogICMgRXh0cmFjdCB5X2hhdCB2YWx1ZXMKICBpZiAobW9kX2RpID09IDApewogICAgZGkgPSBtb2RfZGkoeT15LHg9eCxvcmlnPW9yaWcsbT1tLCB0YXU9dGF1LCBlbmQgPSBlbmQsIHByaW50X21kbCA9IHByaW50X21kbCkKICB9CiAgZWxzZSB7CiAgICBkaSA9IG1vZF9kaV93bCh5PXkseD14LG9yaWc9b3JpZyxtPW0sIHRhdT10YXUsIGFyX3RmID0gYXJfdGYsIHAgPSBwLCBwcmludF9tZGwgPSBwcmludF9tZGwsIG1vZGVsID0gbW9kZWwsIGVuZCA9IGVuZCkKICB9CiAgIyBtb2RfZGlfd2wgPSBmdW5jdGlvbiAoeSwgeCwgb3JpZywgbSwgdGF1LCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEpCiAgeWhhdCA9IGRpJHloYXRbMTooZW5kLW9yaWcpXQogICMgQ2FsY3VsYXRlIHRoZSBsb3NzCiAgIyBJbml0aWFsaXplIGxvc3MgdmVjdG9yCiAgbHZlYyA9IHJlcCgwLChlbmQtb3JpZykpCiAgIyBUYWtlIHRoZSBkaWZmZXJlbmNlCiAgZm9yIChpIGluIDE6KGVuZC1vcmlnKSl7CiAgICAjIENhbGN1bGF0ZSBhbiBpbmRpY2F0b3IgdmFyaWFibGUKICAgIGluZCA9IGlmZWxzZSh5W29yaWcraV0gPCB5aGF0W2ldLCAxLDApCiAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgIGx2ZWNbaV0gPSAodGF1IC0gaW5kKSooeVtvcmlnK2ldIC0geWhhdFtpXSkKICB9CiAgIyBBZGQgdXAgdGhlIGxvc3NlcyAtIGNoYW5nZSB0byBsb29rIGF0IHN1bSBvZiBsb3NzZXMuIFdvbid0IGNoYW5nZSBkZWNpc2lvbiBjcml0ZXJpb24KICBzdW1sb3NzID0gc3VtKGx2ZWMpCiAgIyBzdW1sb3NzID0gc3VtKGx2ZWMpL2xlbmd0aChsdmVjKQogIHJldHVybihsaXN0KHN1bWxvc3MsbHZlYykpCn0KCgpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gdGhhdCBzZWxlY3RzIHRoZSBvcHRpbWFsIG51bWJlciBvZiBwcmVkaWN0b3JzCiMnCiMnIEBwYXJhbSB5IC0gcmVzcG9uc2UgdmVjdG9yCiMnIEBwYXJhbSB4IC0gcHJlZGljdG9yIHZhcmlhYmxlcwojJyBAcGFyYW0gb3JpZyAtIGZvcmVjYXN0IG9yaWdpbgojJyBAcGFyYW0gZW5kIC0gZW5kaW5nIG9mIHZhbGlkYXRpb24gc2V0CiMnIEBwYXJhbSB0YXUgLSBWYVIgaW4gcXVlc3Rpb24KIycgQHBhcmFtIGxvd19tIC0gbG93IHZhbHVlIG9mIG0gdG8gY29uc2lkZXIKIycgQHBhcmFtIGhpZ2hfbSAtIGhpZ2ggdmFsdWUgb2YgbSB0byBjb25zaWRlcgojJwojJyBAcmV0dXJuIC0gcmV0dXJucyB0aGUgb3B0aW1hbCB2YWx1ZSBvZiBtCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gb3B0X20ocGNfZGZbLDFdLCBwY19kZlssLTFdLCA3NTcsIDEwMjcsIDAuMDEsIGxvd19tID0xLCBoaWdoX20gID0gNSkKb3B0X20gPSBmdW5jdGlvbih5LCB4LCBvcmlnLCBlbmQgPSBOVUxMLCB0YXUsIGxvd19tID0gMSwgaGlnaF9tLCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHAgPSAxLCBwcmludF9tZGwgPSAwLCBtb2RlbCA9IDEsIHJvd25hbWUgPSBOVUxMKXsKICAjIEluaXRpYWxpemUgYSBsb3NzIHZlY3RvcgogIGxvc3NfdmVjID0gcmVwKDAsaGlnaF9tLWxvd19tICsgMSkKICAjIEluaXRpYWxpemUgYW4gbSB2ZWN0b3IKICBtX3ZlYyA9IHNlcShsb3dfbSwgaGlnaF9tLCBieSA9IDEpCiAgIyBMb29wIHRocm91Z2ggYW5kIHBvcHVsYXRlIHRoZSBsb3NzIHZlY3RvcgogIGZvciAoaSBpbiAxOmxlbmd0aChsb3NzX3ZlYykpewogICAgbG9zc192ZWNbaV0gPSBxdWlldChsb3NzX2NhbGMoeT15LHg9eCxvcmlnPW9yaWcsZW5kPWVuZCwgbSA9IG1fdmVjW2ldLCB0YXUgPSB0YXUsIG1vZF9kaSA9IG1vZF9kaSwgYXJfdGYgPSBhcl90ZiwgcCA9IHAsIHByaW50X21kbCA9IHByaW50X21kbCwgbW9kZWwgPSBtb2RlbCkpW1sxXV0KICB9CiAgIyBGaW5kIHRoZSBtaW5pbWl6ZXIKICBvcHRfbSA9IHdoaWNoLm1pbihsb3NzX3ZlYykKICBvcHRfcCA9IE5BCiAgIyBDb21iaW5lIGludG8gYSBkYXRhIGZyYW1lCiAgZGYgPSBhcy5kYXRhLmZyYW1lKGNiaW5kKG9wdF9tLCBvcHRfcCkpCiAgbmFtZXMoZGYpIDwtIGMoIk9wdGltYWwgbSIsICJPcHRpbWFsIHAiKQogICMgQXNzaWduIGEgcm93bmFtZQogIGlmIChpcy5udWxsKHJvd25hbWUpID09IFRSVUUpewogICAgIyBXcml0ZSB0aGUgcm93IG5hbWVzCiAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSIikKICB9CiAgZWxzZSB7CiAgICByb3duYW1lcyhkZikgPC0gcm93bmFtZQogIH0KICAjIFJldHVybiB0aGUgbG9zc192ZWN0b3IgYW5kIHRoZSBtaW5pbXplcgogIHJldHVybihsaXN0KG9wdF9tLCBsb3NzX3ZlYywgZGYpKQp9CmBgYAoKYGBge3J9CiMnIEZ1bmN0aW9uIHRoYXQgc2VsZWN0cyB0aGUgb3B0aW1hbCBudW1iZXIgb2YgbGFncwojJwojJyBAcGFyYW0geSAtIHJlc3BvbnNlIHZlY3RvcgojJyBAcGFyYW0geCAtIHByZWRpY3RvciB2YXJpYWJsZXMKIycgQHBhcmFtIG9yaWcgLSBmb3JlY2FzdCBvcmlnaW4KIycgQHBhcmFtIGVuZCAtIGVuZGluZyBvZiB2YWxpZGF0aW9uIHNldAojJyBAcGFyYW0gdGF1IC0gVmFSIGluIHF1ZXN0aW9uCiMnIEBwYXJhbSBsb3dfbSAtIGxvdyB2YWx1ZSBvZiBtIHRvIGNvbnNpZGVyCiMnIEBwYXJhbSBoaWdoX20gLSBoaWdoIHZhbHVlIG9mIG0gdG8gY29uc2lkZXIKIycKIycgQHJldHVybiAtIHJldHVybnMgdGhlIG9wdGltYWwgdmFsdWUgb2YgbQojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIG9wdF9tcCh5ID0gcGNfZGZbLDFdLCB4ID0gcGNfZGZbLC0xXSwgb3JpZyA9IDc1NywgZW5kID0gMTAwNywgdGF1ID0gMC4wMSwgbG93X20gPTEsIGhpZ2hfbSAgPSA1LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCBhcl90ZiA9IDIsIG1vZF9kaSA9IDEpCm9wdF9tcCA9IGZ1bmN0aW9uKHksIHgsIG9yaWcsIGVuZCA9IE5VTEwsIHRhdSwgbG93X20gPSAxLCBoaWdoX20sIGxvd19wID0gMSwgaGlnaF9wLCBtb2RfZGkgPSAwLCBhcl90ZiA9IDEsIHByaW50X21kbCA9IDAsIG1vZGVsID0gMSwgcHJpbnRfbXAgPSAwLCByb3duYW1lID0gTlVMTCl7CiAgIyBJbml0aWFsaXplIGEgbG9zcyBtYXRyaXgKICBsb3NzX21hdCA9IG1hdHJpeCgwLCBoaWdoX3AtbG93X3AgKyAxLGhpZ2hfbS1sb3dfbSArIDEpCiAgIyBJbml0aWFsaXplIGEgcCB2ZWN0b3IKICBwX3ZlYyA9IHNlcShsb3dfcCwgaGlnaF9wLCBieSA9IDEpCiAgIyBMb29wIHRocm91Z2ggYW5kIHBvcHVsYXRlIHRoZSBsb3NzIHZlY3RvcgogIGZvciAoaSBpbiAxOm5yb3cobG9zc19tYXQpKXsKICAgIGxvc3NfbWF0W2ksXSA9IG9wdF9tKHkgPSB5LCB4ID0geCwgb3JpZyA9IG9yaWcsIGVuZCA9IGVuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gID0gaGlnaF9tLCBwID0gaSwgbW9kX2RpID0gbW9kX2RpLCBhcl90ZiA9IGFyX3RmLCBwcmludF9tZGwgPSBwcmludF9tZGwsIG1vZGVsID0gbW9kZWwpW1syXV0KICB9CiAgIyBGaW5kIHRoZSBtaW5pbWl6ZXIKICBvcHRfcCA9IHdoaWNoKGxvc3NfbWF0ID09IG1pbihsb3NzX21hdCksIGFyci5pbmQgPSBUUlVFKVsxLDFdCiAgb3B0X20gPSB3aGljaChsb3NzX21hdCA9PSBtaW4obG9zc19tYXQpLCBhcnIuaW5kID0gVFJVRSlbMSwyXQogICMgUHJpbnQgdGhlIG9wdGltYWwgcCBhbmQgb3B0aW1hbCBtCiAgZGYgPSBhcy5kYXRhLmZyYW1lKGNiaW5kKG9wdF9tLCBvcHRfcCkpCiAgbmFtZXMoZGYpIDwtIGMoIk9wdGltYWwgbSIsICJPcHRpbWFsIHAiKQogICMgQXNzaWduIGEgcm93bmFtZQogIGlmIChpcy5udWxsKHJvd25hbWUpID09IFRSVUUpewogICAgaWYgKGFyX3RmID09IDEpewogICAgICAjIFdyaXRlIHRoZSByb3cgbmFtZXMKICAgICAgcm93bmFtZXMoZGYpIDwtIGMoIk1WIENBVmlhUiArIEFSIikKICAgIH0gZWxzZSBpZiAoYXJfdGYgPT0gMil7CiAgICAgICMgV3JpdGUgdGhlIHJvdyBuYW1lcwogICAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSICsgU0FWIikKICAgIH0gZWxzZSBpZiAoYXJfdGYgPT0gMyl7CiAgICAgICMgV3JpdGUgdGhlIHJvdyBuYW1lcwogICAgICByb3duYW1lcyhkZikgPC0gYygiTVYgQ0FWaWFSICsgQVMiKQogICAgfSBlbHNlIHsKICAgICAgcm93bmFtZXMoZGYpIDwtIGMoIlVua25vd24gTW9kZWwiKQogICAgfQogIH0KICBlbHNlIHsKICAgIHJvd25hbWVzKGRmKSA8LSByb3duYW1lCiAgfQogICMgUHJpbnQgdGhlIGRmIGlmIHRoZSBvcHRpb24gaXMgdHVybmVkIG9uCiAgaWYgKHByaW50X21wID09IDEpewogICAgcHJpbnQoZGYpCiAgfQogICMgUmV0dXJuIHRoZSBsb3NzX3ZlY3RvciBhbmQgdGhlIG1pbmltemVyCiAgcmV0dXJuKGxpc3Qob3B0X20sIG9wdF9wLCBsb3NzX21hdCwgZGYpKQp9CmBgYAoKCmBgYHtyfQojJyBBIGZ1bmN0aW9uIHRoYXQgY29tYmluZXMgb3B0aW1hbCB2YWx1ZXMgb2YgbSBhbmQgcCBpbnRvIGEgZmluYWwgdGFibGUKIycKIycgQHBhcmFtIG0xIC0gdGhlIGRhdGEgZnJhbWUgZnJvbSB0aGUgIk1WIENBVmlhUiIgcnVuCiMnIEBwYXJhbSBtMiAtIHRoZSBkYXRhIGZyYW1lIGZyb20gdGhlICJNViBDQVZpYVIgKyBBUiIgcnVuCiMnIEBwYXJhbSBtMyAtIHRoZSBkYXRhIGZyYW1lIGZyb20gdGhlICJNViBDQVZpYVIgKyBTQVYiIHJ1bgojJyBAcGFyYW0gbTQgLSB0aGUgZGF0YSBmcmFtZSBmcm9tIHRoZSAiTVYgQ0FWaWFSICsgQVMiIHJ1bgojJwojJyBAcmV0dXJuIC0gYSBuaWNlbHkgZm9ybWF0dGVkIHRhYmxlCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzIC0gcHJldHR5X3BtKG9wdF9wcmVkX25sW1szXV0sIG9wdF9wbV9tMVtbNF1dLCBvcHRfcG1fbTJbWzRdXSwgb3B0X3BtX20zW1s0XV0pCnByZXR0eV9wbSA9IGZ1bmN0aW9uKG0xLCBtMiwgbTMsIG00KXsKICAjIE1lcmdlIHRoZSBpbmRpdmlkdWFsIGRhdGEgZnJhbWVzCiAgcG1fcHJldHR5X2RmID0gcmJpbmQobTEsIG0yLCBtMywgbTQpCiAgIyBGb3JtYXQgbmljZWx5CiAgcG1fcHJldHR5X2RmICU+JSBrYWJsZShjYXB0aW9uID0gIk9wdGltYWwgTnVtYmVyIG9mIERpZmZ1c2lvbiBJbmRpY2VzIChtKSBhbmQgTGFncyAocCkgZm9yIERpZmZlcmVudCBNb2RlbHMiLCBkaWdpdHMgPSAwKSAlPiUga2FibGVfc3R5bGluZygic3RyaXBlZCIsIGZ1bGxfd2lkdGggPSBGKSAlPiUga2FibGVfc3R5bGluZygpICU+JSBmb290bm90ZShnZW5lcmFsID0gIlRoZSBNViBDQVZpYVIgbW9kZWwgZG9lc24ndCBoYXZlIGFuIG9wdGltYWwgdmFsdWUgZm9yIHAgYmVjYXVzZSB0aGVyZSBhcmUgbm8gQVIgbGFncyBpbiB0aGUgbW9kZWwiCiAgKQogIAp9CgpgYGAKCgpgYGB7cn0KIycgSGVyZSBpcyBhIGZ1bmN0aW9uIHRoYXQgcnVucyB0aGUgdW5pdmFyaWF0ZSBDQVZpYVIgbW9kZWwgNCB0aW1lcwojJwojJyBAcGFyYW0gZGYgLSB0aGUgcGVyY2VudCBjaGFuZ2UgZGF0YSBmcmFtZSB0byBjb25zaWRlcgojJyBAcGFyYW0gbmZjc3QgLSBudW1iZXIgb2YgZm9yZWNhc3RzIHRvIHJ1bgojJyBAcGFyYW0gdGF1IC0gdGhlIFZhUiBsZXZlbCB0byBjb25zaWRlcgojJyBAcGFyYW0gbm9fcnVuIC0gc3BlY2lmaWVzIGlmIGFueSBtb2RlbHMgc2hvdWxkIG5vdCBiZSBydW4KIycKIycgQHJldHVybiAtIGEgbGlzdCBvZiB0aGUgNCB1bml2YXJpYXRlIG1vZGVsIGZvcmVjYXN0cwojJyBAZXhwb3J0CiMnCiMnIEBleGFtcGxlcyAtIGFjZWcgPSBnZW5fdXZfdGVzdChwY19kZiwgMSwgMC4wNSwgbm9fcnVuID0gYygxLDEsMCwxKSkKZ2VuX3V2X3Rlc3QgPSBmdW5jdGlvbihkZiwgbmZjc3QsIHRhdSwgbm9fcnVuID0gYygwLDAsMCwwKSl7CiAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKICAjIEluaXRpYWxpemUgYSBsaXN0ICAKICBvdXRfbGlzdCA9IGxpc3QoKQogICMgUnVuIHRoZSBmb3VyIG1vZGVscyAtIG1vZGVsIDE7IFNBVgogIGlmIChub19ydW5bMV0gPT0gMCl7CiAgICB1dmNhdl8xID0gcm9sbGluZ19wcmVkaWN0aW9ucyhkZlssMV0sIHJhbmdlX2RhdGEgPSAoMTpsZW5ndGgoZGZbLDFdKSksIG5mY3N0ID0gbmZjc3QsIG1vZGVsID0gMSwgRyA9IDEwLCBjb2wgPSAxLCBsZXZlbCA9IHRhdSkKICB9CiAgIyBBZGQgYSBmaWxsZXIgaWYgdGhlcmUncyBubyBlbnRyeQogIGVsc2UgewogICAgdXZjYXZfMSA9IDAKICB9CiAgIyBNb2RlbCAyIC0gQVMKICBpZiAobm9fcnVuWzJdID09IDApewogICAgdXZjYXZfMiA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDIsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfMiA9IDAKICB9CiAgIyBNb2RlbCAzIC0gR0FSQ0gKICBpZiAobm9fcnVuWzNdID09IDApewogICAgdXZjYXZfMyA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDMsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfMyA9IDAKICB9CiAgIyBNb2RlbCA0IC0gQWRhcHRpdmUKICBpZiAobm9fcnVuWzRdID09IDApewogICAgdXZjYXZfNCA9IHJvbGxpbmdfcHJlZGljdGlvbnMoZGZbLDFdLCByYW5nZV9kYXRhID0gKDE6bGVuZ3RoKGRmWywxXSkpLCBuZmNzdCA9IG5mY3N0LCBtb2RlbCA9IDQsIEcgPSAxMCwgY29sID0gMSwgbGV2ZWwgPSB0YXUpCiAgfQogIGVsc2UgewogICAgdXZjYXZfNCA9IDAKICB9CiAgIyBFeHBvcnQgdGhlIGRhdGEgYXMgYSBsaXN0CiAgcmV0dXJuKGxpc3QodXZjYXZfMSwgdXZjYXZfMiwgdXZjYXZfMywgdXZjYXZfNCkpCn0KCmBgYAoKYGBge3J9CiMnIEZ1bmN0aW9uIHRvIHBsb3QgdGhlIGRhdGEgd2hpY2ggd2UgZ2VuZXJhdGUgaW4gcHJldmlvdXMgZnVuY3Rpb25zCiMnCiMnIEBwYXJhbSBwbG90X21hdHJpeCAtIG1hdHJpeCB3aXRoIHRoZSBkYXRhIHRvIHBsb3QKIycgQHBhcmFtIG5vcm1fdmFsdWUgLSB3aGF0IHRvIHN1YnRhY3QgZnJvbSB0aGUgZGF0YSB0byBtYWtlIGl0IG9uIGEgcGVyY2VudGFnZSBjaGFuZ2UgYmFzaXMuIERlZmF1bHQgaXMgMTAwLgojJwojJyBAcmV0dXJuIAojJyBAZXhwb3J0IC0gYSBwbG90IG9mIHRoZSBkYXRhIGJ5IGRpZmZ1c2lvbiBpbmRleCBudW1iZXIKIycKIycgQGV4YW1wbGVzID0gcGx0X2RhdGEocGxvdF9tdHhbWzFdXSksIGFiYyA9IHBsdF9kYXRhKHBsb3RfbWF0LCB0YXUgPSAwLjAxKQpwbHRfZGF0YSA9IGZ1bmN0aW9uKHBsb3RfbWF0cml4LCB0YXUsIHJlc3BfdmFyLCBudGVzdCl7CiAgIyBFc3RhYmxpc2ggYSBtYXhpbXVtIGFuZCBtaW5pbXVtIHZhbHVlCiAgbWF4X3ZhbCA9IG1heChwbG90X21hdHJpeFssMTpuY29sKHBsb3RfbWF0cml4KV0pCiAgbWluX3ZhbCA9IG1pbihwbG90X21hdHJpeFssMTpuY29sKHBsb3RfbWF0cml4KV0pCiAgIyBDYWxjdWxhdGUgaW5pdGFsIGFuZCBlbmRpbmcgdGltZSB2YWx1ZQogIHN0YXJ0ID0gaW5kZXgocGxvdF9tYXRyaXgpWzFdCiAgZW5kID0gaW5kZXgocGxvdF9tYXRyaXgpW25yb3cocGxvdF9tYXRyaXgpXQogIGluZF92YWxzID0gaW5kZXgocGxvdF9tYXRyaXgpIC0gc3RhcnQKICAjIENyZWF0ZSBhbiBpbml0aWFsIHBsb3QgYW5kIGFkZCBsaW5lcwogICAgZm9yIChpIGluIDE6bmNvbChwbG90X21hdHJpeCkpewogICAgICBpZiAoaSA9PSAxKXsKICAgICAgICAjIDQvMi8yMDIwIC0gZml4aW5nIHRoZSBpbmRleAogICAgICAgIHBsb3QudHMoaW5kX3ZhbHMscGxvdF9tYXRyaXhbLGldLCB0eXBlID0gImwiLCB4bGFiID0gcGFzdGUoIkRheXMgU2luY2UiLCBhcy5EYXRlKHN0YXJ0KSksIHlsYWIgPSAiUGVyY2VudCBDaGFuZ2UgaW4gUEciLCB5bGltID0gYyhtaW5fdmFsLG1heF92YWwpLCBsd2QgPSAxLCBtYWluID0gcGFzdGUoIlByZWRpY3RpbmciLCByZXNwX3ZhciwgIlJldHVybnMgZnJvbSIsIGFzLkRhdGUoc3RhcnQpLCAidG8iLCBhcy5EYXRlKGVuZCkpLCBzdWIgPSBwYXN0ZSgiVGhlIFZhUiBMZXZlbCBpcyAiLCAxMDAqdGF1LCAiJSIsICI7IFRoZXJlIGFyZSAiLCBudGVzdCwgIiBUcmFkaW5nIERheXMgUGxvdHRlZCBBYm92ZSIsIHNlcCA9ICIiKSkKICAgICAgICAjIHBsb3QudHMoaW5kZXgocGxvdF9tYXRyaXgpLCBwbG90X21hdHJpeFssaV0sIHR5cGUgPSAibCIsIHhsYWIgPSAiVHJhZGluZyBEYXlzIiwgeWxhYiA9ICJQZXJjZW50IENoYW5nZSBpbiBQRyIsIHlsaW0gPSBjKG1pbl92YWwsbWF4X3ZhbCksIGx3ZCA9IDEsIG1haW4gPSAiUHJlZGljdGluZyBQRyBSZXR1cm5zIE92ZXIgTGFzdCAyNTAgVHJhZGluZyBEYXlzIGluIDIwMDgiLCBzdWIgPSBwYXN0ZSgiVGhlIFZhUiBMZXZlbCBpcyAiLCAxMDAqdGF1LCAiJSIsIHNlcCA9ICIiKSkKICAgIH0gZWxzZSBpZihpICVpbiUgc2VxKDIsOCwxKSkgewogICAgICAgIGxpbmVzKGluZF92YWxzLHBsb3RfbWF0cml4WyxpXSwgY29sID0gaS0xLCBsdHkgPSAyKQogICAgfSBlbHNlIHsKICAgICAgICBsaW5lcyhpbmRfdmFscyxwbG90X21hdHJpeFssaV0sIGNvbCA9IGktMSwgbHR5ID0gMiwgbHdkID0gMikKICAgIH0KICAgIH0KICAjIERlZmluZSBhIHNlcXVlbmNlIGZvciBwbG90dGluZwogIHBsb3Rfc2VxID0gc2VxKDEsIG5jb2wocGxvdF9tYXRyaXgpKQogIGxlZ2VuZCgidG9wbGVmdCIsIGxlZ2VuZCA9IGMoY29sbmFtZXMocGxvdF9tYXRyaXgpKSwgY29sID0gcGxvdF9zZXEsIGx0eSA9IGMoMSwgcmVwKDIsIDcpLCByZXAoMywgaWZlbHNlKG5jb2wocGxvdF9tYXRyaXgpLTggPD0gMCwgMCwgbmNvbChwbG90X21hdHJpeCktOCkpKSwgbHdkID0gYygxLCByZXAoMSwgNyksIHJlcCgyLCBpZmVsc2UobmNvbChwbG90X21hdHJpeCktOCA8PSAwLCAwLCBuY29sKHBsb3RfbWF0cml4KS04KSkpKQogICMgQWRkIGEgbGluZSBmb3IgMAogICMgYWJsaW5lKGggPSAwLCBjb2wgPSAiYmxhY2siLCBsdHkgPSAyKQp9CgoKYGBgCgpgYGB7cn0KIycgQSBmdW5jdGlvbiB0byBjYWxjdWxhdGUgbG9zc2VzIGJhc2VkIG9uIHRoZSB0ZXN0IHNhbXBsZQojJwojJyBAcGFyYW0gdHJ1ZV92ZWMgLSB0aGUgdHJ1ZSB2ZWN0b3Igb2YgcmV0dXJucwojJyBAcGFyYW0gcHJlZF92ZWMgLSB0aGUgcHJlZGljdGVkIHZlY3RvciBmcm9tIHRoZSBtb2RlbCBydW5zCiMnIEBwYXJhbSB0YXUgLSBWYVIgbGV2ZWwuIE11c3QgbWF0Y2ggd2hhdCB0aGUgbW9kZWwgdXNlZAojJwojJyBAcmV0dXJuIC0gdG90YWwgbG9zc2VzIGFuZCB0aGUgZW50aXJlIGxvc3MgdmVjdG9yCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzCmxvc3NfdGVzdCA9IGZ1bmN0aW9uKHRydWVfdmVjLCBwcmVkX3ZlYywgdGF1KXsKICAjIEluaXRpYWxpemUgYSBsb3NzIHZlY3RvcgogIGx2ZWMgPSByZXAoMCwgbGVuZ3RoKHRydWVfdmVjKSkKICAjIEluaXRpYWxpemUgYSBicmVhayB2ZWN0b3IgdG8gc2VlIHdoZW4gVmFSIGlzIGJyb2tlbgogIGJ2ZWMgPSByZXAoMCwgbGVuZ3RoKHRydWVfdmVjKSkKICBmb3IgKGkgaW4gMTpsZW5ndGgodHJ1ZV92ZWMpKXsKICAgICMgQ2FsY3VsYXRlIGFuIGluZGljYXRvciB2YXJpYWJsZQogICAgYnZlY1tpXSA9IGlmZWxzZSh0cnVlX3ZlY1tpXSA8IHByZWRfdmVjW2ldLCAxLDApCiAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgIGx2ZWNbaV0gPSAodGF1IC0gYnZlY1tpXSkqKHRydWVfdmVjW2ldIC0gcHJlZF92ZWNbaV0pCiAgfQogICMgQWRkIHVwIHRoZSBsb3NzZXMKICAjIHN1bWxvc3MgPSBzdW0obHZlYykvbGVuZ3RoKGx2ZWMpCiAgc3VtbG9zcyA9IHN1bShsdmVjKQogICMgQWRkIHVwIHRoZSBWYVIgYnJlYWthZ2UKICB2YXJicmVhayA9IHN1bShidmVjKS9sZW5ndGgoYnZlYykKICByZXR1cm4obGlzdChzdW1sb3NzLGx2ZWMsIHZhcmJyZWFrLCBidmVjKSkKfQpgYGAKCgoKYGBge3J9CiMnIEEgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGxvc3NlcyBiYXNlZCBvbiB0aGUgcGxvdCBtYXRyaXgKIycKIycgQHBhcmFtIGRhdGFfbWF0IC0gYSBtYXRyaXggb2YgZm9yZWNhc3RlZCBWYVIgdmFsdWVzLCB3aXRoIHRoZSB0cnVlIHZhbHVlIGluIHRoZSBmaXJzdCBjb2x1bW4KIycgQHBhcmFtIHRhdSAtIFZhUiBsZXZlbC4gTXVzdCBtYXRjaCB3aGF0IHRoZSBtb2RlbCB1c2VkCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgZm91ciBpdGVtcy4gCiMnIDEgPSBhIHZlY3RvciBvZiB0aGUgbG9zc2VzIG9mIGFsbCBtb2RlbHMuIAojJyAyID0gYSB2ZWN0b3Igc2hvd2luZyB0aGUgcGVyY2VudGFnZSBvZiBWYVIgYnJlYWtzIGJ5IG1vZGVsCiMnIDMgPSB0aGUgbG9zcyBtYXRyaXgKIycgNCA9IHRoZSBicmVhayBtYXRyaXgKIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKZ2VuX2xvc3NfdGVzdCA9IGZ1bmN0aW9uKGRhdGFfbWF0LCB0YXUpewogICMgSW5pdGlhbGl6ZSBsb3NzIGFuZCBicmVhayBtYXRyaWNlcwogIGxtYXQgPSBibWF0ID0gbWF0cml4KDAsIG5yb3cgPSBucm93KGRhdGFfbWF0KSwgbmNvbCA9IG5jb2woZGF0YV9tYXQpLTEpCiAgIyBidmVjID0gcmVwKDAsIGxlbmd0aCh0cnVlX3ZlYykpCiAgIyBQb3B1bGF0ZSB0aGUgbWF0cmljZXMKICBmb3IgKGkgaW4gMTpucm93KGxtYXQpKXsKICAgIGZvciAoaiBpbiAxOihuY29sKGxtYXQpKSl7CiAgICAgICMgQ2FsY3VsYXRlIGFuIGluZGljYXRvciB2YXJpYWJsZQogICAgICBibWF0W2ksal0gPSBpZmVsc2UoZGF0YV9tYXRbaSwxXSA8IGRhdGFfbWF0W2ksaisxXSwgMSwwKQogICAgICAjIFVzZSBpbmRpY2F0b3IgaW4gZnVuY3Rpb24gYmVsb3cKICAgICAgbG1hdFtpLGpdID0gKHRhdSAtIGJtYXRbaSxqXSkqKGRhdGFfbWF0W2ksMV0gLSBkYXRhX21hdFtpLGorMV0pCiAgICB9ICAgIAogIH0KICAjIEFkZCB1cCB0aGUgbG9zc2VzCiAgc3VtbG9zcyA9IGNvbFN1bXMobG1hdCkKICAjIEFkZCB1cCB0aGUgVmFSIGJyZWFrYWdlCiAgdmFyYnJlYWsgPSBjb2xTdW1zKGJtYXQpL25yb3coYm1hdCkKICByZXR1cm4obGlzdChzdW1sb3NzLCB2YXJicmVhaywgbG1hdCwgYm1hdCkpCn0KYGBgCgoKCmBgYHtyfQojJyBBIGZ1bmN0aW9uIHRvIG1ha2UgYSBuaWNlIGNvbXBhcmlzb24gb2YgbG9zc2VzCiMnCiMnIEBwYXJhbSBkYXRhX21hdCAtIGlucHV0IGRhdGEgbWF0cml4IHVzZWQgaW4gdGhlIGNhbGN1bGF0aW9uIG9mIGxvc3NlcwojJyBAcGFyYW0gbG9zc19saXN0IC0gYSBsaXN0IG9mIHRoZSBsb3NzZXMgY2FsY3VsYXRlZCBmcm9tIHRoZSBDQVZpYVIgZnVuY3Rpb24KIycgQHBhcmFtIHRhdSAtIHRoZSByaXNrIGxldmVsIHVzZWQKIycgQHBhcmFtIG50ZXN0IC0gdGhlIG51bWJlciBvZiB0ZXN0IHBvaW50cwojJwojJyBAcmV0dXJuCiMnIEBleHBvcnQgLSByZXR1cm5zIGEgbmljZWx5IGZvcm1hdHRlZCB0YWJsZQojJwojJyBAZXhhbXBsZXMgLSBwcmV0dHlfdGFibGVzKHBsb3RfbWF0LCBsX2xpc3QsIHRhdSA9IDAuMDEpCnByZXR0eV90YWJsZXMgPSBmdW5jdGlvbihkYXRhX21hdCwgbG9zc19saXN0LCB0YXUsIG50ZXN0KXsKICAjIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUKICBkZiA9IGFzLmRhdGEuZnJhbWUocmJpbmQobG9zc19saXN0W1sxXV0sIGxvc3NfbGlzdFtbMl1dKSkKICAjIENhbGN1bGF0ZSBpbml0YWwgYW5kIGVuZGluZyB0aW1lIHZhbHVlCiAgc3RhcnQgPSBpbmRleChkYXRhX21hdClbMV0KICBlbmQgPSBpbmRleChkYXRhX21hdClbbnJvdyhkYXRhX21hdCldCiAgIyBBZGQgcm93L2NvbHVtbiBuYW1lcwogIGNvbG5hbWVzKGRmKSA8LSBjb2xuYW1lcyhkYXRhX21hdFssLTFdKQogIHJvd25hbWVzKGRmKSA8LSBjKCJMb3NzZXMiLCAiVmFSIEJyZWFrcyAoJSkiKQogICMgQ29udmVydCB0byBhIHRhYmxlCiAgZGYgJT4lIGthYmxlKGNhcHRpb24gPSBwYXN0ZSgiQ29tcGFyaXNvbiBvZiBWYVIgTWV0aG9kcyBmb3IgYSAiLCB0YXUqMTAwLCAiJSBWYVIiLCBzZXAgPSAiIiksIGRpZ2l0cyA9IDMpICU+JSBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgZnVsbF93aWR0aCA9IEYpICU+JSBrYWJsZV9zdHlsaW5nKCkgJT4lIGZvb3Rub3RlKGdlbmVyYWwgPSBwYXN0ZSgiQ2FsY3VsYXRlZCB1c2luZyIsIG50ZXN0LCAidHJhZGluZyBkYXlzIGZyb20iLCBhcy5EYXRlKHN0YXJ0KSwgInRvIiwgYXMuRGF0ZShlbmQpKSkKfQpgYGAKCmBgYHtyfQojJyBBIGRyZXNzZWQgdXAgdmVyc2lvbiBvZiB0aGUgZXhwb3J0IGZ1bmN0aW9uCiMnCiMnIEBwYXJhbSB2YXJfZmlsZSAtIGZpbGUgdG8gZXhwb3J0CiMnIEBwYXJhbSBwYXRoIC0gZmlsZXBhdGgKIycgQHBhcmFtIGZpbGVuYW1lIC0gbmFtZSBvZiB0aGUgZmlsZSwgZW5kaW5nIHdpdGggLkNTVgojJwojJyBAcmV0dXJuCiMnIEBleHBvcnQgLSBleHBvcnRlZCBDU1YgZmlsZQojJwojJyBAZXhhbXBsZXMgLSBleHBfZnVuYyh2YXJfZmlsZSA9IHZhcl8xcGNfMjAxNl91c2V0ZltbMV1dLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAiVEVTVC5jc3YiKQpleHBfZnVuYyA9IGZ1bmN0aW9uKHZhcl9maWxlLCBwYXRoLCBmaWxlbmFtZSl7CiAgIyBXcml0ZSBhIHpvbwogIHdyaXRlLnpvbyh2YXJfZmlsZSwgcGFzdGUwKHBhdGgsIGZpbGVuYW1lKSwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIiwiKQp9CgojIGV4cF9mdW5jKHZhcl9maWxlID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0sIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJURVNULmNzdiIpCgpgYGAKCgoKCiMgQmlnIFNpbXVsYXRpb24gRnVuY3Rpb24KCmBgYHtyfQojJyBUaGlzIGlzIHRoZSAibWFzdGVyIiBmdW5jdGlvbiB3aGVyZSB3ZSdsbCBldmFsdWF0ZSB0aGUgaW1wb3J0YW5jZSBvZiB0aGUgVmFSIG1vZGVsIG92ZXIgc2V2ZXJhbCB0aW1lIHBlcmlvZHMKIycKIycgQHBhcmFtIHN5bWJvbF9saXN0IC0gYSBsaXN0IG9mIHN5bWJvbHMgdG8gZmVlZCBpbnRvIHRoZSBtb2RlbCAKIycgQHBhcmFtIHJlc3BfdmFyIC0gdGhlIHJlc3BvbnNlIHZhcmlhYmxlCiMnIEBwYXJhbSBjb21wbF9jYXNlIC0gc2hvdWxkIHRoZSBtb2RlbCByZXF1aXJlIGNvbXBsZXRlIGNhc2VzPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSBhZGpfY2xvc2UgLSB1c2UgYWRqdXN0ZWQgY2xvc2UgcHJpY2UgZm9yIHRoZSBwcmVkaWN0b3JzPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSByZXNwX2Fkal9jbG9zZSAtIHVzZSBhZGp1c3RlZCBjbG9zZSBwcmljZSBmb3IgdGhlIHJlc3BvbnNlPyBEZWZhdWx0IHZhbHVlIGlzIDEuCiMnIEBwYXJhbSBzdGFydF9kYXRlIC0gc3RhcnQgZGF0ZSB0byBwdWxsIGRhdGEgZnJvbQojJyBAcGFyYW0gZW5kX2RhdGUgLSBlbmQgZGF0ZSB0byBwdWxsIGRhdGEgZnJvbQojJyBAcGFyYW0gbnZhbCAtIG51bWJlciBvZiB2YWxpZGF0aW9uIHBvaW50cyB0byB1c2UKIycgQHBhcmFtIG50ZXN0IC0gbnVtYmVyIG9mIHRlc3QgcG9pbnRzIHRvIHVzZQojJyBAcGFyYW0gdGF1IC0gVmFSIGxldmVsIHRvIHVzZQojJyBAcGFyYW0gbG93X20gLSBsb3cgbnVtYmVyIG9mIHByZWRpY3RvcnMgdG8gdGVzdAojJyBAcGFyYW0gaGlnaF9tICAtIGxvdyBudW1iZXIgb2YgcHJlZGljdG9ycyB0byB0ZXN0CiMnIEBwYXJhbSB1dl9saXN0IC0gYSBsaXN0IG9mIGEgcHJlLXJ1biB1bml2YXJpYXRlIG1vZGVsLiBJZiBhIGRhdGEgZnJhbWUgaXMgbm90IHByb3ZpZGVkLCB0aGUgbGVuZ3RoeSB1diBtb2RlbCB3aWxsIHJ1biAKIycgQHBhcmFtIG5vX3J1biAtIHRoaW5ncyBub3QgdG8gcnVuIGluIHRoZSBtb2RlbAojJyBAcGFyYW0gbG93X3AgLSBsb3cgdmFsdWUgZm9yIG51bWJlciBvZiBsYWdzCiMnIEBwYXJhbSBoaWdoX3AgLSBoaWdoIHZhbHVlIGZvciBudW1iZXIgb2YgbGFncwojJyBAcGFyYW0gbmFfaW50ZXJwIC0gc2hvdWxkIHRoZSBmdW5jdGlvbiBpbnRlcnBvbGF0ZSBOQSdzCiMnIEBwYXJhbSBwcmludF9tZGwgLSBwcmludCB0aGUgbW9kZWwgc3VtbWFyaWVzPwojJyBAcGFyYW0gcHJpbnRfbXAgLSBwcmludCB0aGUgb3B0aW1hbCB2YWx1ZXMgZm9yIHAgYW5kIG0KIycgQHBhcmFtIGxhZ19wcmVkIC0gZG8geW91IHdhbnQgdG8gbGFnIHRoZSBtIHByZWRpY3RvcnMgKGRlZmF1bHQgaXMgMTsgc3Ryb25nbHkgcmVjb21tZW5kZWQpCiMnIEBwYXJhbSByb3duYW1lIC0gd2hhdCB0byBuYW1lIHRoZSByb3dzIG9mIHRoZSBuaWNlIHAgYW5kIG0gbWF0cml4CiMnIEBwYXJhbSBleHBvcnRfY3N2IC0gZG8geW91IHdhbnQgdG8gZXhwb3J0IGEgQ1NWPyBEZWZhdWx0IGlzIDEuCiMnIEBwYXJhbSBwYXRoIC0gcGF0aCB0byBleHBvcnQgdGhlIENTVgojJyBAcGFyYW0gZmlsZW5hbWUgLSB3aGF0IHRvIG5hbWUgdGhlIENTVgojJwojJyBAcmV0dXJuIC0gYSBsaXN0IG9mIHRoZSBwbG90IG1hdHJpeCwgYSBwbG90LCBhIGxpc3Qgd2l0aCBsb3NzZXMsIGFuZCBhIHRhYmxlCiMnIEBleHBvcnQgLSBhIHBsb3QgYW5kIGEgdGFibGUKIycKIycgQGV4YW1wbGVzIC0gY2F2X3NpbXVsKGMoIkRJUyIsICJHRSIsICJJQk0iLCAiTU1NIiwgIlhPTSIpLCByZXNwX3ZhciA9ICJQRyIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA1LCB0YXUgPSAwLjAxLCB1dl9saXN0ID0gdXZfY2F2X2xpc3QpCmNhdl9zaW11bCA9IGZ1bmN0aW9uKHN5bWJvbF9saXN0LCByZXNwX3ZhciwgY29tcGxfY2FzZSA9IDEsIGFkal9jbG9zZSA9IDEsIHJlc3BfYWRqX2Nsb3NlID0gMSwgc3RhcnRfZGF0ZSA9ICIxOTAwLTAxLTAxIiwgZW5kX2RhdGUgPSBTeXMuRGF0ZSgpLCBudmFsLCBudGVzdCwgdGF1LCBsb3dfbSA9IDEsIGhpZ2hfbSwgbG93X3AgPSAxLCBoaWdoX3AsIHV2X2xpc3QgPSBOVUxMLCBub19ydW4gPSBjKDAsMCwwLDApLCBuYV9pbnRlcnAgPSBUUlVFLCBwcmludF9tZGwgPSAwLCBwcmludF9tcCA9IDAsIGxhZ19wcmVkID0gMSwgcm93bmFtZSA9IE5VTEwsIGV4cG9ydF9jc3YgPSAxLCBwYXRoLCBmaWxlbmFtZSl7CiAgIyBTZWxlY3QgZGF0YSBwYXJhbWV0ZXJzLCBwdWxsIHRoZSBkYXRhLCBhbmQgcGVyY2VudCBjaGFuZ2UgdGhlIGRhdGEKICBkZiA9IGRpZmZfaW5kZXhfZGYoc3ltYm9sX2xpc3QgPSBzeW1ib2xfbGlzdCwgcmVzcF92YXIgPSByZXNwX3ZhciwgY29tcGxfY2FzZSA9IGNvbXBsX2Nhc2UsIGFkal9jbG9zZSA9IGFkal9jbG9zZSwgcmVzcF9hZGpfY2xvc2UgPSByZXNwX2Fkal9jbG9zZSwgc3RhcnRfZGF0ZSA9IHN0YXJ0X2RhdGUsIGVuZF9kYXRlID0gZW5kX2RhdGUsIGxhZ19wcmVkID0gbGFnX3ByZWQpCiAgIyBUYWtlIHRoZSBwZXJjZW50IGNoYW5nZSBvZiB0aGUgZGF0YQogIHBjX2RmID0gcGNfZGlmZl9pbmRleChkZikKICAjIEV4dHJhY3QgdGhlIGxlZ250aCBvZiB0aGUgZGF0YSBmcmFtZQogIG5yID0gdGVzdF9lbmQgPSBucm93KHBjX2RmKQogICMgQ2FsY3VsYXRlIHRoZSBzdGFydCBvZiB0aGUgdmFsIHBlcmlvZCwgdGhlIGVuZCBvZiB0aGUgdmFsIHBlcmlvZCwgYW5kIHRoZSBiZWdpbm5pbmcgYW5kIGVuZCBvZiB0ZXN0IHBlcmlvZAogIHRlc3Rfb3JpZyA9IHRlc3RfZW5kIC0gbnRlc3QKICB2YWxfZW5kID0gdGVzdF9vcmlnCiAgdmFsX29yaWcgPSB0ZXN0X29yaWcgLSBudmFsCiAgIyBUZXN0IGZvciB0aGUgb3B0aW1hbCBudW1iZXIgb2YgcGFyYW1ldGVycwogIG9wdF9wcmVkX25sID0gb3B0X20oeSA9IHBjX2RmWywxXSwgeCA9IHBjX2RmWywtMV0sIG9yaWcgPSB2YWxfb3JpZywgZW5kID0gdmFsX2VuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gPSBoaWdoX20sIHJvd25hbWUgPSByb3duYW1lKQogIG9wdF9wcmVkX2FydDEgPSBvcHRfbXAoeSA9IHBjX2RmWywxXSwgeCA9IHBjX2RmWywtMV0sIG9yaWcgPSB2YWxfb3JpZywgZW5kID0gdmFsX2VuZCwgdGF1ID0gdGF1LCBsb3dfbSA9IGxvd19tLCBoaWdoX20gPSBoaWdoX20sIGxvd19wID0gbG93X3AsIGhpZ2hfcCA9IGhpZ2hfcCxtb2RfZGkgPSAxLCBhcl90ZiA9IDEsIHByaW50X21kbCA9IHByaW50X21kbCwgcHJpbnRfbXAgPSBwcmludF9tcCwgcm93bmFtZSA9IHJvd25hbWUpCiAgb3B0X3ByZWRfYXJ0MiA9IG9wdF9tcCh5ID0gcGNfZGZbLDFdLCB4ID0gcGNfZGZbLC0xXSwgb3JpZyA9IHZhbF9vcmlnLCBlbmQgPSB2YWxfZW5kLCB0YXUgPSB0YXUsIGxvd19tID0gbG93X20sIGhpZ2hfbSA9IGhpZ2hfbSwgbG93X3AgPSBsb3dfcCwgaGlnaF9wID0gaGlnaF9wLG1vZF9kaSA9IDEsIGFyX3RmID0gMiwgcHJpbnRfbWRsID0gcHJpbnRfbWRsLCBwcmludF9tcCA9IHByaW50X21wLCByb3duYW1lID0gcm93bmFtZSkKICBvcHRfcHJlZF9hcnQzID0gb3B0X21wKHkgPSBwY19kZlssMV0sIHggPSBwY19kZlssLTFdLCBvcmlnID0gdmFsX29yaWcsIGVuZCA9IHZhbF9lbmQsIHRhdSA9IHRhdSwgbG93X20gPSBsb3dfbSwgaGlnaF9tID0gaGlnaF9tLCBsb3dfcCA9IGxvd19wLCBoaWdoX3AgPSBoaWdoX3AsIG1vZF9kaSA9IDEsIGFyX3RmID0gMywgcHJpbnRfbWRsID0gcHJpbnRfbWRsLCBwcmludF9tcCA9IHByaW50X21wLCByb3duYW1lID0gcm93bmFtZSkKICAjIGdlbl91dl90ZXN0KHBjX2RmLCAxLCAwLjA1LCBub19ydW4gPSBjKDEsMSwwLDEpKQogICMgVXNlIHRoZSBhYm92ZSBmb3JlY2FzdHMgdG8gaW5wdXQgaW50byB0aGUgYWJvdmUKICBtdl9mY3N0ID0gbW9kX2RpKHBjX2RmWywxXSwgcGNfZGZbLC0xXSwgb3JpZyA9IHRlc3Rfb3JpZywgbSA9IG9wdF9wcmVkX25sW1sxXV0sIHRhdSA9IHRhdSwgcHJpbnRfbWRsID0gcHJpbnRfbWRsKQogIG12X2Zjc3RfYXJ0MSA9IG1vZF9kaV93bChwY19kZlssMV0sIHBjX2RmWywtMV0sIG9yaWcgPSB0ZXN0X29yaWcsIG0gPSBvcHRfcHJlZF9hcnQxW1sxXV0sIHAgPSBvcHRfcHJlZF9hcnQxW1syXV0sIHRhdSA9IHRhdSwgYXJfdGYgPSAxLCBwcmludF9tZGwgPSBwcmludF9tZGwpCiAgbXZfZmNzdF9hcnQyID0gbW9kX2RpX3dsKHBjX2RmWywxXSwgcGNfZGZbLC0xXSwgb3JpZyA9IHRlc3Rfb3JpZywgbSA9IG9wdF9wcmVkX2FydDJbWzFdXSwgcCA9IG9wdF9wcmVkX2FydDJbWzJdXSwgdGF1ID0gdGF1LCBhcl90ZiA9IDIsIHByaW50X21kbCA9IHByaW50X21kbCkKICBtdl9mY3N0X2FydDMgPSBtb2RfZGlfd2wocGNfZGZbLDFdLCBwY19kZlssLTFdLCBvcmlnID0gdGVzdF9vcmlnLCBtID0gb3B0X3ByZWRfYXJ0M1tbMV1dLCBwID0gb3B0X3ByZWRfYXJ0M1tbMl1dLCB0YXUgPSB0YXUsIGFyX3RmID0gMywgcHJpbnRfbWRsID0gcHJpbnRfbWRsKQogICMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcHJlZGljdGlvbnMKICBpZiAoaXMubnVsbCh1dl9saXN0KSA9PSBUUlVFKXsKICAgICMgUHJpbnQgYSB3YXJuaW5nCiAgICBwcmludCgiV0FSTklORzogTm90IHN1cHBseWluZyBhbiBpbnB1dCBkYXRhIGZyYW1lIHdpbGwgcmVxdWlyZSB0aGlzIGZ1bmN0aW9uIHRvIHJ1biBmb3IgYSBzaWduaWZpY2FudCBhbW91bnQgb2YgdGltZSAoMWhyKykiKQogICAgIyBDYWxsIHRoZSBmdW5jdGlvbgogICAgIyBnZW5fdXZfdGVzdCA9IGZ1bmN0aW9uKGRmLCBuZmNzdCwgdGF1LCBub19ydW4gPSBjKDAsMCwwLDApKXsKICAgICMgcHJpbnQoaGVhZChwY19kZikpCiAgICB1dl9saXN0ID0gZ2VuX3V2X3Rlc3QoZGYgPSBwY19kZiwgbmZjc3QgPSBudGVzdCwgdGF1ID0gdGF1LCBub19ydW4gPSBub19ydW4pCiAgICAjIEFkZCB0byBhIGRhdGEgZnJhbWUKICAgICMgSW5jb3Jwb3JhdGUgdGhlIHJvbGxpbmcgcHJlZGljdGlvbnMgZnVuY3Rpb24gcmVzdWx0cyBoZXJlCiAgcGxvdF9tYXQgPSBjYmluZChwY19kZlsodGVzdF9vcmlnKzEpOm5yb3cocGNfZGYpLDFdLCBtdl9mY3N0JHloYXRbMTpudGVzdF0sIG12X2Zjc3RfYXJ0MSR5aGF0WzE6bnRlc3RdLCBtdl9mY3N0X2FydDIkeWhhdFsxOm50ZXN0XSwgbXZfZmNzdF9hcnQzJHloYXRbMTpudGVzdF0sIHV2X2xpc3RbWzFdXVsodGVzdF9vcmlnKzEpOnRlc3RfZW5kXSooLTEpLCB1dl9saXN0W1syXV1bKHRlc3Rfb3JpZysxKTp0ZXN0X2VuZF0qKC0xKSwgdXZfbGlzdFtbM11dWyh0ZXN0X29yaWcrMSk6dGVzdF9lbmRdKigtMSksIHV2X2xpc3RbWzRdXVsodGVzdF9vcmlnKzEpOnRlc3RfZW5kXSooLTEpKQogIH0gZWxzZSB7CiAgICAjIEFzc2lnbiB0aGUgY29sdW1ucyBvZiB0aGUgZGF0YSBmcmFtZQogICAgIyBoZWFkKHZhcl81cGNfMjAxMF91c2V0ZltbMV1dWyw2OjldKQogICAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKSAKICAgICMgdGVzdF9kZiA9IGhlYWQodmFyXzVwY18yMDEwX3VzZXRmW1sxXV1bLDY6OV0pCiAgICAjIHRlc3RfZGYkU0FWCiAgICAjIHRlc3RfZGYkYEFicy4gU2xvcGVgCiAgICAjIHRlc3RfZGYkYEluZC4gR0FSQ0hgCiAgICAjIHRlc3RfZGYkQWRhcHRpdmUKICAgIHBsb3RfbWF0ID0gY2JpbmQocGNfZGZbKHRlc3Rfb3JpZysxKTpucm93KHBjX2RmKSwxXSwgbXZfZmNzdCR5aGF0WzE6bnRlc3RdLCBtdl9mY3N0X2FydDEkeWhhdFsxOm50ZXN0XSwgbXZfZmNzdF9hcnQyJHloYXRbMTpudGVzdF0sIG12X2Zjc3RfYXJ0MyR5aGF0WzE6bnRlc3RdLCB1dl9saXN0JFNBViwgdXZfbGlzdCRgQWJzLiBTbG9wZWAsIHV2X2xpc3QkYEluZC4gR0FSQ0hgLCB1dl9saXN0JEFkYXB0aXZlKQogIH0KICAjIENvdW50IHRoZSBOQXMgYW5kIHByaW50IGEgd2FybmluZwogIHByaW50KHBhc3RlKCJOT1RFOiBUaGVyZSBhcmUgIiwgc3VtKGlzLm5hKHBsb3RfbWF0KSksICIgTkEocykgaW4gdGhlIGRhdGFzZXQiLCBzZXAgPSAiIikpCiAgIyBMaW5lYXJseSBpbnRlcnBvbGF0ZSB0aGUgTkFzCiAgaWYgKG5hX2ludGVycCA9PSBUUlVFKXsKICAgICMgQXNzaWduIHRoZSBwbG90IG1hdHJpeCB0byBhIG5ldyB2YWx1ZQogICAgcGxvdF9tYXRfbmEgPC0gcGxvdF9tYXQKICAgICMgUHJpbnQgYSB3YXJuaW5nCiAgICBwcmludCgiV0FSTklORzogVGhlcmUgd2VyZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgcGxvdCBtYXRyaXguIikKICAgICMgSW50ZXJwb2xhdGUgdGhlIE5BJ3MKICAgIGZvciAoaSBpbiAxOm5jb2wocGxvdF9tYXRfbmEpKXsKICAgICAgIyBJbnRlcnBvbGF0ZSB0aGUgZGF0YQogICAgICBwbG90X21hdFssaV0gPC0gbmEuYXBwcm94KHBsb3RfbWF0X25hWyxpXSkKICAgIH0KICB9CiAgIyBtb2RlbCB0eXBlICgxIC0gU0FWLCAyIC0gQVMsIDMgLSBHQVJDSCwgNCAtIEFEQVBUSVZFKQogICMgQWRkIGRlc2NyaXB0aXZlIHRpdGxlcyBvbnRvIHRoZSBwbG90X21hdAogIGNvbG5hbWVzKHBsb3RfbWF0KSA8LSBjKHJlc3BfdmFyLCAiTVYgQ0FWaWFSIiwgIk1WIENBVmlhUiArIEFSIiwgIk1WIENBVmlhUiArIFNBViIsICJNViBDQVZpYVIgKyBBUyIsICJTQVYiLCAiQWJzLiBTbG9wZSIsICJJbmQuIEdBUkNIIiwgIkFkYXB0aXZlIikKICAjIGNvbG5hbWVzKHBsb3RfbWF0KSA8LSBjKCJTUFkiLCAiTVYgQ0FWaWFSIiwgIk1WIENBVmlhUiArIEFSIiwgIk1WIENBVmlhUiArIFNBViIsICJNViBDQVZpYVIgKyBBUyIsICJTQVYiLCAiQWJzLiBTbG9wZSIsICJJbmQuIEdBUkNIIiwgIkFkYXB0aXZlIikKICAjIFBsb3QgZXZlcnl0aGluZwogIHBsb3QgPSBwbHRfZGF0YShwbG90X21hdCwgdGF1ID0gdGF1LCByZXNwX3ZhciA9IHJlc3BfdmFyLCBudGVzdCA9IG50ZXN0KQogICMgQ2FsY3VsYXRlIGxvc3NlcwogIGxfbGlzdCA9IGdlbl9sb3NzX3Rlc3QocGxvdF9tYXQsIHRhdSA9IHRhdSkKICAjIFB1dCBpbnRvIHRhYmxlcwogIHRhYmxlcyA9IHByZXR0eV90YWJsZXMocGxvdF9tYXQsIGxfbGlzdCwgdGF1ID0gdGF1LCBudGVzdCA9IG50ZXN0KQogICMgUnVuIHRoZSBmdW5jdGlvbiBmb3Igb3B0aW1hbCBwIGFuZCBtCiAgcG1fdGFibGUgPSBwcmV0dHlfcG0ob3B0X3ByZWRfbmxbWzNdXSwgb3B0X3ByZWRfYXJ0MVtbNF1dLCBvcHRfcHJlZF9hcnQyW1s0XV0sIG9wdF9wcmVkX2FydDNbWzRdXSkKICAjIEV4cG9ydCB0aGUgbWF0cml4CiAgaWYgKGV4cG9ydF9jc3YgPT0gMSl7CiAgICBleHBfZnVuYyh2YXJfZmlsZSA9IHBsb3RfbWF0LCBwYXRoLCBmaWxlbmFtZSkKICB9CiAgIyBQcmludCB0aGUgdGFibGVzIGFuZCB0aGUgcGxvdAogIHByaW50KHBsb3QpCiAgcHJpbnQodGFibGVzKQogIHByaW50KHBtX3RhYmxlKQogIHJldHVybihsaXN0KHBsb3RfbWF0LCBwbG90LCBsX2xpc3QsIHRhYmxlcywgcGxvdF9tYXRfbmEsIHBtX3RhYmxlKSkKfQpgYGAKCgoKYGBge3J9CiMnIEEgZnVuY3Rpb24gdG8gaW5wdXQgdGhlIFZhUiBmaWxlcywgcGxvdCB0aGVtIGFuZCBnZW5lcmF0ZSB0YWJsZXMKIycKIycgQHBhcmFtIGZpbGVfcGF0aCAtIGZpbGUgcGF0aCB0byB1c2UKIycgQHBhcmFtIGZpbGVuYW1lIC0gbmFtZSBvZiB0aGUgZmlsZQojJyBAcGFyYW0gdGF1IC0gcXVhbnRpbGUgdG8gdXNlCiMnIEBwYXJhbSByZXNwX3ZhciAtIHJlc3BvbnNlIHZhcmlhYmxlIHRvIHVzZSBpbiB0aGUgcGxvdAojJyBAcGFyYW0gbnRlc3QgLSBudW1iZXIgb2YgdGVzdCBwb2ludHMKIycgQHBhcmFtIGNuX2lucHV0IC0gY29sdW1uIG5hbWUgaW5wdXRzCiMnCiMnIEByZXR1cm4gLSBhIGxpc3Qgb2YgdGhlIHh0cyBmaWxlLCB0aGUgcGxvdCwgdGhlIGxvc3MgbGlzdCwgYW5kIHRhYmxlcwojJyBAZXhwb3J0IC0gYSBwbG90IGFuZCB0YWJsZXMKIycKIycgQGV4YW1wbGVzIC0gdGVzdCA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF91c19ldGYuY3N2IiwgMC4wMSkKdmFyX2lucHV0X2Rpc3AgPSBmdW5jdGlvbihmaWxlX3BhdGgsIGZpbGVuYW1lLCB0YXUsIHJlc3BfdmFyID0gIlNQWSIsIG50ZXN0ID0gMjUwLCBjbl9pbnB1dCA9IGMoIlNQWSIsICJNMSIsICJNMiIsICJNMyIsICJNNCIsICJNNSIsICJNNiIsICJNNyIsICJNOCIpKXsKIyB2YXJfaW5wdXRfZGlzcCA9IGZ1bmN0aW9uKGZpbGVfcGF0aCwgZmlsZW5hbWUsIHRhdSwgcmVzcF92YXIgPSAiU1BZIiwgbnRlc3QgPSAyNTAsIGNuX2lucHV0ID0gYygiU1BZIiwgIk1WIENBVmlhUiIsICJNViBDQVZpYVIgKyBBUiIsICJNViBDQVZpYVIgKyBTQVYiLCAiTVYgQ0FWaWFSICsgQVMiLCAiU0FWIiwgIkFicy4gU2xvcGUiLCAiSW5kLiBHQVJDSCIsICJBZGFwdGl2ZSIpKXsKICAjIEltcG9ydCBkYXRhCiAgcGxvdF9tYXQgPSByZWFkLmNzdihwYXN0ZTAoZmlsZV9wYXRoLGZpbGVuYW1lKSwgc2VwID0gIiwiLCBoZWFkZXIgPSBULCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCiAgIyBGaXggZGF0ZSBmb3JtYXQKICBwbG90X21hdCRJbmRleCA9IGFzLkRhdGUocGxvdF9tYXQkSW5kZXgpCiAgIyBDb252ZXJ0IHRvIGFuIHh0cwogIHBsb3RfbWF0ID0geHRzKHBsb3RfbWF0WywtMV0sIG9yZGVyLmJ5ID0gcGxvdF9tYXRbLDFdKQogICMgRml4IGNvbHVtbiBuYW1lcwogIGNvbG5hbWVzKHBsb3RfbWF0KSA8LSBjbl9pbnB1dAogICMgUGxvdCBldmVyeXRoaW5nCiAgcGx0X2RhdGEocGxvdF9tYXQsIHRhdSA9IHRhdSwgcmVzcF92YXIgPSByZXNwX3ZhciwgbnRlc3QgPSBudGVzdCkKICAjIHBsb3QgPSBwbHRfZGF0YShwbG90X21hdCwgdGF1ID0gdGF1LCByZXNwX3ZhciA9IHJlc3BfdmFyLCBudGVzdCA9IG50ZXN0KQogICMgQ2FsY3VsYXRlIGxvc3NlcwogIGxfbGlzdCA9IGdlbl9sb3NzX3Rlc3QocGxvdF9tYXQsIHRhdSA9IHRhdSkKICAjIFB1dCBpbnRvIHRhYmxlcwogIHBtX3RhYmxlID0gcHJldHR5X3RhYmxlcyhwbG90X21hdCwgbF9saXN0LCB0YXUgPSB0YXUsIG50ZXN0ID0gbnRlc3QpCiAgIyBQcmludCB0aGUgdGFibGVzIGFuZCB0aGUgcGxvdAogICMgcHJpbnQocGxvdCkKICAjIHByaW50KHRhYmxlcykKICBwcmludChwbV90YWJsZSkKICAjIFJldHVybiB0aGUgeHRzLCB0aGUgcGxvdCwgdGhlIGxvc3MgbGlzdCwgYW5kIHRoZSB0YWJsZXMKICByZXR1cm4obGlzdChwbG90X21hdCkpCiAgIyByZXR1cm4obGlzdChwbG90X21hdCwgcGxvdCwgbF9saXN0LCB0YWJsZXMpKQp9CmBgYAoKCiMgUHJvYmxlbSBTb2x2aW5nIG9uIDQuMjkuMjAyMAoKCgojIyAyMDA4IEVuZGluZwoKIyMjIFUuUy4gRVRGcwoKYGBge3J9CiMgcmV0dXJuKGxpc3QocGxvdF9tYXQsIHBsb3QsIGxfbGlzdCwgdGFibGVzKSkKCiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAwOF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF91c19ldGYuY3N2IiwgMC4wMSkKIyBwcmV0dHlfdGFibGVzKHYxXzIwMDhfdXNldGZbWzFdXSwgdjFfMjAwOF91c2V0ZltbM11dLCB0YXUgPSAwLjAxLCBudGVzdCA9IDI1MCkKdjVfMjAwOF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl81cGNfMjAwOF91c19ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMDhfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDA4X3VzX2V0Zi5jc3YiLCAwLjEwKQoKIyBoZWFkKHYxMF8yMDA4X3VzZXRmW1sxXV0pCiMgdjEwXzIwMDhfdXNldGYKYGBgCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDA4IC0gMXN0IHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDA4X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDA4X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAwOF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDA4X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMDhfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMDhfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDA4X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEdsb2JhbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDA4X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl8xcGNfMjAwOF9nbG9iX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDA4X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl81cGNfMjAwOF9nbG9iX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAwOF9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDA4X2dsb2JfZXRmLmNzdiIsIDAuMTApCmBgYAoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAwOCAtIDJuZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAwOF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAwOF9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAwOF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDA4X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAwOF9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAwOF9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAwOF91c2V0ZltbMV1dKQpgYGAKCiMjIyBDb21tb2RpdHkgRVRGcwoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAwOCAtIDNyZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAwOF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDA4X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDA4X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9jb21tX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAwOF9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMDhfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAwOF9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAwOF91c2V0ZltbMV1dKQpgYGAKCgoKIyMjIEJvbmQgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAwOF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMDhfYm9uZF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAwOF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMDhfYm9uZF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMDhfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAwOF9ib25kX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIGlTaGFyZXMgMS0zIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChTSFkpCiMgaVNoYXJlcyA3LTEwIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChJRUYpCiMgaVNoYXJlcyAyMCsgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFRMVCkKIyBpU2hhcmVzIGlCb3h4ICQgSW52ZXN0bWVudCBHcmFkZSBDb3Jwb3JhdGUgQm9uZCBFVEYgKExRRCkKCiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAwOCAtIDR0aCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAwOF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDA4X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDA4X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAwOF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDA4X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMDhfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAwOF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAwOF91c2V0ZltbMV1dKQpgYGAKCiMjIyBBbGwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAwOF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzFwY18yMDA4X2FsbF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAwOF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzVwY18yMDA4X2FsbF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMDhfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMDhfYWxsX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMDggLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMDhfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMDgtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAwOF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDA4X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDQtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDA4LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAwOF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMDhfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAwOF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA0LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAwOC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDA4X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMDhfdXNldGZbWzFdXSkKYGBgCgojIyAyMDEwIEVuZGluZwoKIyMjIFUuUy4gRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxMF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxMF91c19ldGYuY3N2IiwgMC4wMSkKdjVfMjAxMF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl81cGNfMjAxMF91c19ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTBfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDEwX3VzX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTAgLSAxc3Qgc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTBfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTBfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDEwX3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTBfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxMF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxMF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTBfdXNldGZbWzFdXSkKYGBgCgojIyMgR2xvYmFsIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTBfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzFwY18yMDEwX2dsb2JfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTBfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzVwY18yMDEwX2dsb2JfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDEwX2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgMC4xMCkKYGBgCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDEwIC0gMm5kIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDEwX2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDEwX2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDEwX2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTBfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDEwX2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDEwX3VzZXRmW1sxXV0pCmBgYAoKIyMjIENvbW1vZGl0eSBFVEZzCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDEwIC0gM3JkIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDEwX2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTBfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxMF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTBfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDEwX2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxMF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDEwX3VzZXRmW1sxXV0pCmBgYAoKIyMjIEJvbmQgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxMF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTBfYm9uZF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxMF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTBfYm9uZF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTBfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxMF9ib25kX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIGlTaGFyZXMgMS0zIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChTSFkpCiMgaVNoYXJlcyA3LTEwIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChJRUYpCiMgaVNoYXJlcyAyMCsgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFRMVCkKIyBpU2hhcmVzIGlCb3h4ICQgSW52ZXN0bWVudCBHcmFkZSBDb3Jwb3JhdGUgQm9uZCBFVEYgKExRRCkKCiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxMCAtIDR0aCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxMF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDEwX2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDEwX2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxMF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDEwX3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTBfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxMF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxMF91c2V0ZltbMV1dKQpgYGAKCiMjIyBBbGwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxMF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzFwY18yMDEwX2FsbF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxMF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzVwY18yMDEwX2FsbF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTBfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTBfYWxsX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTAgLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTBfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAwNi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTAtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxMF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDEwX2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMDYtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDEwLTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxMF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTBfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxMF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDA2LTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxMC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDEwX2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTBfdXNldGZbWzFdXSkKYGBgCgojIyAyMDE0IEVuZGluZwoKIyMjIFUuUy4gRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxNF91c19ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNF91c2V0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsInZhcl81cGNfMjAxNF91c19ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTRfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDE0X3VzX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTQgLSAxc3Qgc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTRfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTRfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTRfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNF91c19ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTRfdXNldGZbWzFdXSkKYGBgCgojIyMgR2xvYmFsIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTRfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzFwY18yMDE0X2dsb2JfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTRfZ2xvYmV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwidmFyXzVwY18yMDE0X2dsb2JfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE0X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTRfZ2xvYl9ldGYuY3N2IiwgMC4xMCkKYGBgCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE0IC0gMm5kIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE0X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE0X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTRfZ2xvYl9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxNF91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDE0X2dsb2JfZXRmID0gY2F2X3NpbXVsKGMoIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMTAsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE0X3VzZXRmW1sxXV0pCmBgYAoKIyMjIENvbW1vZGl0eSBFVEZzCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE0IC0gM3JkIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE0X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTRfY29tbV9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xcGNfMjAxNF91c2V0ZltbMV1dKQoKIyB2YXJfNXBjXzIwMTRfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE0X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4xMCwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfY29tbV9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE0X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEJvbmQgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTRfYm9uZF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNF9ib25kZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTRfYm9uZF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTRfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNF9ib25kX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIGlTaGFyZXMgMS0zIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChTSFkpCiMgaVNoYXJlcyA3LTEwIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChJRUYpCiMgaVNoYXJlcyAyMCsgWWVhciBUcmVhc3VyeSBCb25kIEZ1bmQgKFRMVCkKIyBpU2hhcmVzIGlCb3h4ICQgSW52ZXN0bWVudCBHcmFkZSBDb3Jwb3JhdGUgQm9uZCBFVEYgKExRRCkKCiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNCAtIDR0aCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNF9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE0X2JvbmRfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE0X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTRfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNF9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNF91c2V0ZltbMV1dKQpgYGAKCiMjIyBBbGwgRVRGcwoKYGBge3J9CiMgQ2FsbCB0aGUgYWJvdmUgZnVuY3Rpb24KdjFfMjAxNF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzFwY18yMDE0X2FsbF9ldGYuY3N2IiwgMC4wMSkKdjVfMjAxNF9hbGxldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwidmFyXzVwY18yMDE0X2FsbF9ldGYuY3N2IiwgMC4wNSkKdjEwXzIwMTRfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTRfYWxsX2V0Zi5jc3YiLCAwLjEwKQpgYGAKCmBgYHtyfQojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTQgLSA1dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTRfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMC0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTQtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE0X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTAtMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE0LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNF9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTRfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNF9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEwLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNC0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMTBwY18yMDE0X2FsbF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTRfdXNldGZbWzFdXSkKYGBgCgoKIyMgMjAxNiBFbmRpbmcKCiMjIyBVLlMuIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTZfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfMXBjXzIwMTZfdXNfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTZfdXNldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9VU19FVEZfcnVucy8iLCJ2YXJfNXBjXzIwMTZfdXNfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE2X3VzZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwidmFyXzEwcGNfMjAxNl91c19ldGYuY3N2IiwgMC4xMCkKYGBgCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gMXN0IHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X3VzX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gOSwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCwgdGF1ID0gMC4wMSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE2X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNl91c19ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDksIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfVVNfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE2X3VzX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTZfdXNfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA5LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX1VTX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMTZfdXNfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyMjIEdsb2JhbCBFVEZzCgpgYGB7cn0KIyBDYWxsIHRoZSBhYm92ZSBmdW5jdGlvbgp2MV8yMDE2X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCAwLjAxKQp2NV8yMDE2X2dsb2JldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsInZhcl81cGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCAwLjA1KQp2MTBfMjAxNl9nbG9iZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfZ2xvYl9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDE2X2dsb2JfZXRmLmNzdiIsIDAuMTApCmBgYAoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNiAtIDJuZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNl9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9nbG9iX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNl9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzVwY18yMDE2X2dsb2JfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfNXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzEwcGNfMjAxNl9nbG9iX2V0ZiA9IGNhdl9zaW11bChjKCJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDEwLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2dsb2JfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNl9nbG9iX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNl91c2V0ZltbMV1dKQpgYGAKCiMjIyBDb21tb2RpdHkgRVRGcwoKYGBge3J9CiMgMSUsIDUlLCAxMCUgVmFSIC0gMjAxNiAtIDNyZCBzZXQgb2YgcHJlZGljdG9ycwojIHZhcl8xcGNfMjAxNl9jb21tX2V0ZiA9IGNhdl9zaW11bChjKCJEQkEiLCAiREJDIiwgIkRCRSIsICJEQkIiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzFwY18yMDE2X2NvbW1fZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMXBjXzIwMTZfdXNldGZbWzFdXSkKCiMgdmFyXzVwY18yMDE2X2NvbW1fZXRmID0gY2F2X3NpbXVsKGMoIkRCQSIsICJEQkMiLCAiREJFIiwgIkRCQiIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjA1LCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9jb21tX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl81cGNfMjAxNl9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTZfY29tbV9ldGYgPSBjYXZfc2ltdWwoYygiREJBIiwgIkRCQyIsICJEQkUiLCAiREJCIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMTAsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2NvbW1fRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNl9jb21tX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzEwcGNfMjAxNl91c2V0ZltbMV1dKQpgYGAKCiMjIyBCb25kIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTZfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzFwY18yMDE2X2JvbmRfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTZfYm9uZGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2JvbmRfRVRGX3J1bnMvIiwidmFyXzVwY18yMDE2X2JvbmRfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE2X2JvbmRldGYgPSB2YXJfaW5wdXRfZGlzcCgiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsInZhcl8xMHBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgMC4xMCkKYGBgCgpgYGB7cn0KIyBpU2hhcmVzIDEtMyBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoU0hZKQojIGlTaGFyZXMgNy0xMCBZZWFyIFRyZWFzdXJ5IEJvbmQgRnVuZCAoSUVGKQojIGlTaGFyZXMgMjArIFllYXIgVHJlYXN1cnkgQm9uZCBGdW5kIChUTFQpCiMgaVNoYXJlcyBpQm94eCAkIEludmVzdG1lbnQgR3JhZGUgQ29ycG9yYXRlIEJvbmQgRVRGIChMUUQpCgojIDElLCA1JSwgMTAlIFZhUiAtIDIwMTYgLSA0dGggc2V0IG9mIHByZWRpY3RvcnMKIyB2YXJfMXBjXzIwMTZfYm9uZF9ldGYgPSBjYXZfc2ltdWwoYygiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSA0LCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLCB0YXUgPSAwLjAxLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xcGNfMjAxNl9ib25kX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNl9ib25kX2V0ZiA9IGNhdl9zaW11bChjKCJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDQsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsdGF1ID0gMC4wNSwgcHJpbnRfbWRsID0gMSwgcHJpbnRfbXAgPSAxLCBwYXRoID0gIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYm9uZF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl81cGNfMjAxNl91c2V0ZltbMV1dKQoKIyB2YXJfMTBwY18yMDE2X2JvbmRfZXRmID0gY2F2X3NpbXVsKGMoIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gNCwgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9ib25kX0VURl9ydW5zLyIsIGZpbGVuYW1lID0gInZhcl8xMHBjXzIwMTZfYm9uZF9ldGYuY3N2IiwgdXZfbGlzdCA9IHZhcl8xMHBjXzIwMTZfdXNldGZbWzFdXSkKYGBgCgojIyMgQWxsIEVURnMKCmBgYHtyfQojIENhbGwgdGhlIGFib3ZlIGZ1bmN0aW9uCnYxXzIwMTZfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl8xcGNfMjAxNl9hbGxfZXRmLmNzdiIsIDAuMDEpCnY1XzIwMTZfYWxsZXRmID0gdmFyX2lucHV0X2Rpc3AoIi9Vc2Vycy9zdGV2ZW5tb2VuL0RvY3VtZW50cy9HaXRIdWIvQ0FWaWFSX01TX3RoZXNpcy9EYXRhX0V4cG9ydC9TUFlfYWxsX0VURl9ydW5zLyIsInZhcl81cGNfMjAxNl9hbGxfZXRmLmNzdiIsIDAuMDUpCnYxMF8yMDE2X2FsbGV0ZiA9IHZhcl9pbnB1dF9kaXNwKCIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCJ2YXJfMTBwY18yMDE2X2FsbF9ldGYuY3N2IiwgMC4xMCkKYGBgCgpgYGB7cn0KIyAxJSwgNSUsIDEwJSBWYVIgLSAyMDE2IC0gNXRoIHNldCBvZiBwcmVkaWN0b3JzCiMgdmFyXzFwY18yMDE2X2FsbF9ldGYgPSBjYXZfc2ltdWwoYygiWExVIiwgIlhMUCIsICJYTFYiLCAiWExLIiwgIlhMWSIsICJYTEkiLCAiWExGIiwgIlhMQiIsICJYTEUiLCAiSlhJIiwgIktYSSIsICJJWEoiLCAiSVhQIiwgIklYTiIsICJSWEkiLCAiRVhJIiwgIklYRyIsICJNWEkiLCAiSVhDIiwgIlNIWSIsICJJRUYiLCAiVExUIiwgIkxRRCIpLCByZXNwX3ZhciA9ICJTUFkiLCBzdGFydF9kYXRlID0gIjIwMTItMDEtMDEiLCBlbmRfZGF0ZSA9ICIyMDE2LTEyLTMxIiwgbnZhbCA9IDI1MCwgbnRlc3QgPSAyNTAsIGxvd19tID0gMSwgaGlnaF9tID0gMjMsIGxvd19wID0gMSwgaGlnaF9wID0gMTAsIHRhdSA9IDAuMDEsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfMXBjXzIwMTZfYWxsX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzFwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl81cGNfMjAxNl9hbGxfZXRmID0gY2F2X3NpbXVsKGMoIlhMVSIsICJYTFAiLCAiWExWIiwgIlhMSyIsICJYTFkiLCAiWExJIiwgIlhMRiIsICJYTEIiLCAiWExFIiwgIkpYSSIsICJLWEkiLCAiSVhKIiwgIklYUCIsICJJWE4iLCAiUlhJIiwgIkVYSSIsICJJWEciLCAiTVhJIiwgIklYQyIsICJTSFkiLCAiSUVGIiwgIlRMVCIsICJMUUQiKSwgcmVzcF92YXIgPSAiU1BZIiwgc3RhcnRfZGF0ZSA9ICIyMDEyLTAxLTAxIiwgZW5kX2RhdGUgPSAiMjAxNi0xMi0zMSIsIG52YWwgPSAyNTAsIG50ZXN0ID0gMjUwLCBsb3dfbSA9IDEsIGhpZ2hfbSA9IDIzLCBsb3dfcCA9IDEsIGhpZ2hfcCA9IDEwLHRhdSA9IDAuMDUsIHByaW50X21kbCA9IDEsIHByaW50X21wID0gMSwgcGF0aCA9ICIvVXNlcnMvc3RldmVubW9lbi9Eb2N1bWVudHMvR2l0SHViL0NBVmlhUl9NU190aGVzaXMvRGF0YV9FeHBvcnQvU1BZX2FsbF9FVEZfcnVucy8iLCBmaWxlbmFtZSA9ICJ2YXJfNXBjXzIwMTZfYWxsX2V0Zi5jc3YiLCB1dl9saXN0ID0gdmFyXzVwY18yMDE2X3VzZXRmW1sxXV0pCgojIHZhcl8xMHBjXzIwMTZfYWxsX2V0ZiA9IGNhdl9zaW11bChjKCJYTFUiLCAiWExQIiwgIlhMViIsICJYTEsiLCAiWExZIiwgIlhMSSIsICJYTEYiLCAiWExCIiwgIlhMRSIsICJKWEkiLCAiS1hJIiwgIklYSiIsICJJWFAiLCAiSVhOIiwgIlJYSSIsICJFWEkiLCAiSVhHIiwgIk1YSSIsICJJWEMiLCAiU0hZIiwgIklFRiIsICJUTFQiLCAiTFFEIiksIHJlc3BfdmFyID0gIlNQWSIsIHN0YXJ0X2RhdGUgPSAiMjAxMi0wMS0wMSIsIGVuZF9kYXRlID0gIjIwMTYtMTItMzEiLCBudmFsID0gMjUwLCBudGVzdCA9IDI1MCwgbG93X20gPSAxLCBoaWdoX20gPSAyMywgbG93X3AgPSAxLCBoaWdoX3AgPSAxMCx0YXUgPSAwLjEwLCBwcmludF9tZGwgPSAxLCBwcmludF9tcCA9IDEsIHBhdGggPSAiL1VzZXJzL3N0ZXZlbm1vZW4vRG9jdW1lbnRzL0dpdEh1Yi9DQVZpYVJfTVNfdGhlc2lzL0RhdGFfRXhwb3J0L1NQWV9hbGxfRVRGX3J1bnMvIiwgZmlsZW5hbWUgPSAidmFyXzEwcGNfMjAxNl9hbGxfZXRmLmNzdiIsIHV2X2xpc3QgPSB2YXJfMTBwY18yMDE2X3VzZXRmW1sxXV0pCmBgYAoKIyBDb25jbHVzaW9ucyBhbmQgRnV0dXJlIFdvcmsKClRoZSBwcm9ibGVtIG9mIGhvdyB0byBwcmVkaWN0IGEgbG93IHF1YW50aWxlIG9mIGEgc3RvY2sncyBsb2cgcmV0dXJuIHdoZW4gdGhlIHRyYWluaW5nIHNhbXBsZSBpcyBzdWJzdGFudGlhbGx5IGRpZmZlcmVudCB0aGFuIHRoZSB0ZXN0IHNjZW5hcmlvIGlzIGFuIGVub3Jtb3VzbHkgZGlmZmljdWx0IHByb2JsZW0uIEFsbW9zdCBheGlvbWF0aWNhbGx5LCB0aGUgZGlzdHJpYnV0aW9uIGlzIG5vbnN0YXRpb25hcnkgb3ZlciB0aW1lLiBIb3cgaXMgaXQgcG9zc2libGUgdG8gcHJlZGljdCB0aGUgcmV0dXJuIG9mIGFuIGluZGV4IGxpa2UgdGhlIFMmUDUwMCBkdXJpbmcgYSBwZXJpb2Qgb2YgbWFya2V0IHR1cm1vaWwgc3VjaCBhcyB0aGUgZ3JlYXQgcmVjZXNzaW9uPyBXaGlsZSB0aGUgQ0FWaWFSIG1vZGVsIHBlcmZvcm1zIGNvbXBhcmF0aXZlbHkgd2VsbCBkdXJpbmcgdGltZXMgb2Ygc3RyZXNzLCBpdCBwZXJmb3JtcyBhYm91dCB0aGUgc2FtZSBhcyB0aGUgbXVsdGl2YXJpYXRlIG1vZGVsIGR1cmluZyBtb3JlIGJlbmlnbiBlY29ub21pYyBwZXJpb2RzLgoKVGhpcyBjb25jbHVzaW9uIGRyYXduIGZyb20gdGhlIGFib3ZlIHJlc3VsdHMgbWlnaHQgc3VwcG9ydCB0aGUgbm90aW9uIG9mIGNvbWJpbmluZyB0aGUgdHdvIG1vZGVscyBpbiBzb21lIHNvcnQgb2YgYSBtaXh0dXJlIG1vZGVsIC0gYWltaW5nIHRvIHVzZSB0aGUgYmFza2V0IG9mIEVURnMgZHVyaW5nIGdvb2QgdGltZXMsIGFuZCB1c2UgdGhlIENBVmlhUiBBUk1BIHNwZWNpZmljYXRpb24gZHVyaW5nIGJhZCB0aW1lcy4gVGhlIGFwcHJvYWNoIG9mIHVzaW5nIEVURnMgYWxsb3dzIGEgcHJlZGljdGlvbiBiYXNlZCBvbiBmb3J3YXJkLWxvb2tpbmcgZXhwZWN0YXRpb25zIG9mIGZ1bmRhbWVudGFsIGZhY3RvcnMuIEluZGVlZCwgRVRGcyBhcmUganVzdCBiYXNrZXRzIG9mIGluZGl2aWR1YWwgc3RvY2tzIG9yIGJvbmRzLCBhbmQgdGhvc2Ugc2VjdXJpdGllcyBhcmUgKGluIHRoZW9yeSkgYmFzZWQgb24gcmF0aW9uYWwgZXhwZWN0YXRpb25zIGFib3V0IGZ1dHVyZSByZXNvdXJjZXMsIG1hcmtldCBjb25kaXRpb25zLCBldGMgLSB0aGUgbWljcm9mb3VuZGF0aW9ucyBvZiB3aGF0IGRyaXZlcyBvdXIgZWNvbm9teS4gVGhlIEFSTUEgc3BlY2lmaWNhdGlvbiwgd2hpbGUgcHJhY3RpY2FsbHkgYW5kIHN0YXRpc3RpY2FsbHkgc291bmQsIGlzIGNvbnRyYWRpY3RlZCBieSBlY29ub21pYyB0aGVvcnkgYW5kIHByYWN0aWNlIC0gdGhlIHdlYWsgZm9ybSBvZiB0aGUgZWZmaWNpZW50IG1hcmtldCBoeXBvdGhlc2lzIHN0YXRlcyB0aGF0IGl0IGlzIGltcG9zc2libGUgdG8gZm9yZWNhc3QgZnV0dXJlIHZhbHVlcyBvZiBhc3NldCBwcmljZXMgdXNpbmcgcGFzdCB2YWx1ZXMuIEJ1dCBwZXJoYXBzIHRoaXMgdmlldyBpcyBpbmNvbXBsZXRlLgoKQW55IG1vZGVsIHRoYXQgYXR0ZW1wdHMgdG8gY2FwdHVyZSByZWxhdGlvbnNoaXBzIGluIHRoZSByZWFsIHdvcmxkIHdpbGwgb25seSB3b3JrIHVudGlsIGFuIG9taXR0ZWQgdmFyaWFibGUgaXMgZm91bmQuIFRoZSBlbGVnYW5jZSBvZiB0aGUgbXVsdGl2YXJpYXRlIENBVmlhUiBtb2RlbCBpcyB0aGF0IGl0IHByb3ZpZGVzIGluc2lnaHQgaW50byB3aHkgYSBwcmVkaWN0aW9uIGlzIHdyb25nOyB0aGUgY2hhbmdlIGluIHRoZSBhbmdsZSBiZXR3ZWVuIHJlc3VsdGFudCB2ZWN0b3JzIGlzIGEgc2Vuc2libGUgbWVhc3VyZW1lbnQgb2YgZWNvbm9taWMgY2hhbmdlcG9pbnRzIChDSEFOR0UpLiBIb3dldmVyLCBlcnJvcnMgaW4gdGhlIHdvcmxkIGFyZSBjb3N0bHksIGFuZCBpdCdzIHdpc2hmdWwgdGhpbmtpbmcgdG8gc2F5IHRoYXQgZXhwbGFpbmluZyB3aHkgdGhlIGVycm9yIG9jY3VyZWQgaXMgc3VmZmljaWVudC4KCkFzIHN1Y2gsIGZvciBmdXR1cmUgd29yayBpdCdzIHdvcnRoIGV4cGxvcmluZyB0aGUgbm90aW9uIG9mIHdlaWdodGluZyBhbiBBUk1BLWFwcHJvYWNoIG1vcmUgaGVhdmlseSB3aGVuIHByZWRpY3Rpb25zIHVzaW5nIGZ1bmRhbWVudGFscyB3ZXJlIHRvbyBoaWdoLCB0aGVuIG5vdCBvbmx5IHdvdWxkIHRoaXMgYWZ0ZXItdGhlLWZhY3QgcmVjb2duaXRpb24gYmUgYWNoaWV2ZXMsIGJ1dCBhbHNvIGEgaGllcmFyY2hpY2FsIG1vZGVsIHRoYXQgY2FwdHVyZXMgZnVuZGFtZW50YWwgcmVsYXRpb25zaGlwcyBpbiB0aGUgZWNvbm9teSBhbmQgcG90ZW50aWFsbHkgY2hhbmdlcyBvdXIgdW5kZXJzdGFuZGluZyBvZiBhc3NldCBwcmljZXMgaW4gZ2VuZXJhbCAtIGEgc3ludGhlc2lzIGJldHdlZW4gS2V5bmVzJyBhbmltYWwgc3Bpcml0cyBkdXJpbmcgYSB0aW1lIG9mIHNldmVyZSBjcmlzaXM7IHdoZXJlIGEgbW9kZWwgY2Fubm90IGV4cGxhaW4gc2hpZnRzLCBhbmQgYSBtb3JlIHJhdGlvbmFsIHdvcmxkIHRoYXQgZXhwbGFpbnMgb3RoZXIgcGVyaW9kcy4gSW4gYWRkaXRpb24gdG8gc2lnbmlmaWNhbnQgcHJlZGljdGl2ZSBwb3dlciBiZWNhdXNlIG9mIHRoZSBzd2l0Y2hpbmcgYmV0d2VlbiB0aGUgdHdvIHdvcmxkcywgdGhlcmUncyBhbHNvIGFuIGVsZWdhbnQgZXhwbGFuYXRpb247IGEgd2F5IHRvIGV4cGxhaW4gY2hhbmdlcyBpbiB0aGUgdXNlZnVsbmVzcyBvZiB0aGUgdW5kZXJwaW5uaW5ncyBpbiB0aGUgZWNvbm9teS4gQmVjYXVzZSBvZiB0aGUgZmxleGliaWxpdHkgb2YgdGhlIG1vZGVsLCBpdCdzIGVudGlyZWx5IHBvc3NpYmxlIHRoYXQgYSB3aG9sZSBnYW11dCBvZiB2YXJpYWJsZXMgY291bGQgYmUgdG9zc2VkIGluIGFuZCBiYWNrdGVzdGVkIHRvIHdoZW4gImNoYW5nZXBvaW50cyIgb2NjdXJyZWQuIAoKQWRkaXRpb25hbCBmdXR1cmUgd29yayBpbnZvbHZlcyBkZXZlbG9waW5nIHRoZW9yZXRpY2FsIGd1YXJhbnRlZXMgb24gdGhlIHBhcmFtZXRlcnMgaW4gdGhlIG11bHRpdmFyaWF0ZSBDQVZpYVIgbW9kZWwuIE9uZSBhZHZhbnRhZ2Ugb2YgYm90aCB0aGUgZGlmZnVzaW9uIGluZGV4IG1vZGVsIGFuZCB0aGUgQ0FWaWFSIG1vZGVsIGlzIHRoYXQgYm90aCBoYXZlIHRoZW9yZW1zIGFib3V0IGFzeW1wdG90aWMgbm9ybWFsaXR5IGFuZCBjb25zaXN0ZW5jeSBbQ09ORklSTV0uCgoKIyBDb2RlIEFwcGVuZGl4CgpgYGB7ciByZWYubGFiZWw9a25pdHI6OmFsbF9sYWJlbHMoKSwgZWNobyA9IFQsIGV2YWwgPSBGfQpgYGAKCiMgTGl0ZXJhdHVyZSBDaXRlZAo=